| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| |
| package org.apache.axis2.jaxws.description.impl; |
| |
| import org.apache.axis2.AxisFault; |
| import org.apache.axis2.addressing.wsdl.WSDL11ActionHelper; |
| import org.apache.axis2.description.AxisMessage; |
| import org.apache.axis2.description.AxisOperation; |
| import org.apache.axis2.description.AxisOperationFactory; |
| import org.apache.axis2.description.AxisService; |
| import org.apache.axis2.description.Parameter; |
| import org.apache.axis2.description.WSDL2Constants; |
| import org.apache.axis2.java.security.AccessController; |
| import org.apache.axis2.jaxws.ExceptionFactory; |
| import org.apache.axis2.jaxws.description.AttachmentDescription; |
| import org.apache.axis2.jaxws.description.EndpointDescriptionJava; |
| import org.apache.axis2.jaxws.description.EndpointInterfaceDescription; |
| import org.apache.axis2.jaxws.description.FaultDescription; |
| import org.apache.axis2.jaxws.description.OperationDescription; |
| import org.apache.axis2.jaxws.description.OperationDescriptionJava; |
| import org.apache.axis2.jaxws.description.OperationDescriptionWSDL; |
| import org.apache.axis2.jaxws.description.OperationRuntimeDescription; |
| import org.apache.axis2.jaxws.description.ParameterDescription; |
| import org.apache.axis2.jaxws.description.ParameterDescriptionJava; |
| import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite; |
| import org.apache.axis2.jaxws.description.builder.FaultActionAnnot; |
| import org.apache.axis2.jaxws.description.builder.MethodDescriptionComposite; |
| import org.apache.axis2.jaxws.description.builder.OneWayAnnot; |
| import org.apache.axis2.jaxws.description.builder.ParameterDescriptionComposite; |
| import org.apache.axis2.jaxws.description.builder.converter.ConverterUtils; |
| import org.apache.axis2.jaxws.i18n.Messages; |
| import org.apache.axis2.jaxws.util.WSDL4JWrapper; |
| import org.apache.axis2.wsdl.WSDLConstants; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import javax.jws.Oneway; |
| import javax.jws.WebMethod; |
| import javax.jws.WebParam; |
| import javax.jws.WebParam.Mode; |
| import javax.jws.WebResult; |
| import javax.jws.soap.SOAPBinding; |
| import javax.wsdl.Binding; |
| import javax.wsdl.BindingInput; |
| import javax.wsdl.BindingOperation; |
| import javax.wsdl.BindingOutput; |
| import javax.wsdl.Definition; |
| import javax.wsdl.extensions.AttributeExtensible; |
| import javax.xml.namespace.QName; |
| import javax.xml.ws.Action; |
| import javax.xml.ws.AsyncHandler; |
| import javax.xml.ws.FaultAction; |
| import javax.xml.ws.RequestWrapper; |
| import javax.xml.ws.Response; |
| import javax.xml.ws.ResponseWrapper; |
| import javax.xml.ws.WebFault; |
| import java.io.File; |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.AnnotatedElement; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.ParameterizedType; |
| import java.lang.reflect.Type; |
| import java.net.URL; |
| import java.security.PrivilegedAction; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.concurrent.Future; |
| |
| /** @see ../OperationDescription */ |
| // TODO: Axis2 does not support overloaded operations, although EndpointInterfaceDescription.addOperation() does support overloading |
| // of methods represented by OperationDescription classes. However, the AxisOperation contained in an OperationDescription |
| // does NOT support overloaded methods. |
| // |
| // While overloading is not supported by WS-I, it IS supported by JAX-WS (p11). |
| // Note that this requires support in Axis2; currently WSDL11ToAxisServiceBuilder.populateOperations does not |
| // support overloaded methods in the WSDL; the operations are stored on AxisService as children in a HashMap with the wsdl |
| // operation name as the key. |
| |
| class OperationDescriptionImpl |
| implements OperationDescription, OperationDescriptionJava, OperationDescriptionWSDL { |
| private EndpointInterfaceDescription parentEndpointInterfaceDescription; |
| private AxisOperation axisOperation; |
| private QName operationQName; |
| private Method seiMethod; |
| private MethodDescriptionComposite methodComposite; |
| private ParameterDescription[] parameterDescriptions; |
| private FaultDescription[] faultDescriptions; |
| private static final Log log = LogFactory.getLog(OperationDescriptionImpl.class); |
| // =========================================== |
| // ANNOTATION related information |
| // =========================================== |
| |
| // ANNOTATION: @Oneway |
| private Oneway onewayAnnotation; |
| private Boolean onewayIsOneway; |
| |
| // ANNOTATION: @XmlList |
| private boolean isListType = false; |
| |
| // ANNOTATION: @RequestWrapper |
| private RequestWrapper requestWrapperAnnotation; |
| private String requestWrapperTargetNamespace; |
| private String requestWrapperLocalName; |
| private String requestWrapperClassName; |
| |
| // ANNOTATION: @ResponseWrapper |
| private ResponseWrapper responseWrapperAnnotation; |
| private String responseWrapperLocalName; |
| private String responseWrapperTargetNamespace; |
| private String responseWrapperClassName; |
| |
| // ANNOTATION: @Action |
| private Action actionAnnotation; |
| |
| // ANNOTATION: @SOAPBinding |
| // Note this is the Method-level annotation. See EndpointInterfaceDescription for the Type-level annotation |
| // Also note this annotation is only allowed on methods if SOAPBinding.Style is DOCUMENT and if the method-level |
| // annotation is absent, the behavior defined on the Type is used. |
| // per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28 |
| private SOAPBinding soapBindingAnnotation; |
| private javax.jws.soap.SOAPBinding.Style soapBindingStyle; |
| public static final javax.jws.soap.SOAPBinding.Style SoapBinding_Style_VALID = |
| javax.jws.soap.SOAPBinding.Style.DOCUMENT; |
| private javax.jws.soap.SOAPBinding.Use soapBindingUse; |
| // Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28 |
| public static final javax.jws.soap.SOAPBinding.Use SOAPBinding_Use_DEFAULT = |
| javax.jws.soap.SOAPBinding.Use.LITERAL; |
| private javax.jws.soap.SOAPBinding.ParameterStyle soapBindingParameterStyle; |
| // Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28 |
| public static final javax.jws.soap.SOAPBinding.ParameterStyle SOAPBinding_ParameterStyle_DEFAULT = |
| javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED; |
| |
| // ANNOTATION: @WebMethod |
| private WebMethod webMethodAnnotation; |
| private String webMethodOperationName; |
| // Default value per JSR-181 MR Sec 4.2, pg 17 |
| public static final String WebMethod_Action_DEFAULT = ""; |
| private String webMethodAction; |
| // Default value per JSR-181 MR sec 4.2, pg 17 |
| public static final Boolean WebMethod_Exclude_DEFAULT = new Boolean(false); |
| private Boolean webMethodExclude; |
| |
| // ANNOTATION: @WebParam |
| private String[] webParamNames; |
| private Mode[] webParamMode; |
| private String[] webParamTargetNamespace; |
| |
| |
| // ANNOTATION: @WebResult |
| private WebResult webResultAnnotation; |
| private String webResultName; |
| private String webResultPartName; |
| // Default value per JSR-181 MR Sec 4.5.1, pg 23 |
| public static final String WebResult_TargetNamespace_DEFAULT = ""; |
| private String webResultTargetNamespace; |
| // Default value per JSR-181 MR sec 4.5, pg 24 |
| public static final Boolean WebResult_Header_DEFAULT = new Boolean(false); |
| private Boolean webResultHeader; |
| |
| // Web Result Attachment Description information |
| private boolean _setAttachmentDesc = false; |
| private AttachmentDescription attachmentDesc = null; |
| |
| private boolean hasRequestSwaRefAttachments = false; |
| private boolean hasResponseSwaRefAttachments = false; |
| private Map<String, AttachmentDescription> partAttachmentMap; |
| |
| private Method serviceImplMethod; |
| private boolean serviceImplMethodFound = false; |
| // For JAX-WS client async methods, this is the corresponding Sync method; for everything else, |
| // this is "this". |
| private OperationDescription syncOperationDescription = null; |
| // RUNTIME INFORMATION |
| Map<String, OperationRuntimeDescription> runtimeDescMap = |
| Collections.synchronizedMap(new HashMap<String, OperationRuntimeDescription>()); |
| // Cache the actual Class of the type being returned. |
| private Class resultActualTypeClazz; |
| |
| OperationDescriptionImpl(Method method, EndpointInterfaceDescription parent) { |
| parentEndpointInterfaceDescription = parent; |
| partAttachmentMap = new HashMap<String, AttachmentDescription>(); |
| setSEIMethod(method); |
| |
| // The operationQName is intentionally unqualified to be consistent with the remaining parts of the system. |
| // Using a qualified name will cause breakage. |
| // Don't do --> this.operationQName = new QName(parent.getTargetNamespace(), getOperationName()); |
| this.operationQName = new QName("", getOperationName()); |
| if (getEndpointInterfaceDescription().getEndpointDescription() != null) { |
| if (!getEndpointInterfaceDescription().getEndpointDescription().getServiceDescription().isServerSide()) { |
| axisOperation = createClientAxisOperation(); |
| } |
| } |
| if(this.axisOperation != null) { |
| try { |
| this.axisOperation.addParameter(new Parameter(OperationDescription.AXIS_OPERATION_PARAMETER, |
| this)); |
| } |
| catch(AxisFault af) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("operationDescriptionErr1")); |
| } |
| } |
| buildAttachmentInformation(); |
| } |
| |
| OperationDescriptionImpl(AxisOperation operation, EndpointInterfaceDescription parent) { |
| parentEndpointInterfaceDescription = parent; |
| partAttachmentMap = new HashMap<String, AttachmentDescription>(); |
| axisOperation = operation; |
| if(this.axisOperation != null) { |
| try { |
| this.axisOperation.addParameter(new Parameter(OperationDescription.AXIS_OPERATION_PARAMETER, |
| this)); |
| } |
| catch(AxisFault af) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("operationDescriptionErr1")); |
| } |
| } |
| this.operationQName = axisOperation.getName(); |
| buildAttachmentInformation(); |
| } |
| |
| OperationDescriptionImpl(MethodDescriptionComposite mdc, |
| EndpointInterfaceDescription parent, |
| AxisOperation axisOperation) { |
| |
| parentEndpointInterfaceDescription = parent; |
| partAttachmentMap = new HashMap<String, AttachmentDescription>(); |
| methodComposite = mdc; |
| // The operationQName is intentionally unqualified to be consistent with the remaining parts of the system. |
| // Using a qualified name will cause breakage. |
| // Don't do --> this.operationQName = new QName(parent.getTargetNamespace(), getOperationName()); |
| this.operationQName = new QName("", getOperationName()); |
| |
| webMethodAnnotation = methodComposite.getWebMethodAnnot(); |
| |
| parameterDescriptions = createParameterDescriptions(); |
| faultDescriptions = createFaultDescriptions(); |
| isListType = mdc.isListType(); |
| buildAttachmentInformation(); |
| |
| //If an AxisOperation was already created for us by populateService then just use that one |
| //Otherwise, create it |
| if (axisOperation != null) { |
| this.axisOperation = axisOperation; |
| } else { |
| this.axisOperation = createAxisOperation(); |
| } |
| |
| if(this.axisOperation != null) { |
| try { |
| this.axisOperation.addParameter(new Parameter(OperationDescription.AXIS_OPERATION_PARAMETER, |
| this)); |
| } |
| catch(AxisFault af) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("operationDescriptionErr1")); |
| } |
| } |
| |
| // Register understood headers on axisOperation |
| registerMustUnderstandHeaders(); |
| } |
| |
| /** |
| * Create an AxisOperation for this Operation. Note that the ParameterDescriptions must |
| * be created before calling this method since, for a DOC/LIT/BARE (aka UNWRAPPED) message, the |
| * ParamaterDescription is used to setup the AxisMessage correctly for use in SOAP Body-based |
| * dispatching on incoming DOC/LIT/BARE messages. |
| */ |
| private AxisOperation createClientAxisOperation() { |
| AxisOperation newAxisOperation = null; |
| try { |
| if (isOneWay()) { |
| newAxisOperation = |
| AxisOperationFactory.getOperationDescription(WSDL2Constants.MEP_URI_OUT_ONLY); |
| } else { |
| newAxisOperation = |
| AxisOperationFactory.getOperationDescription(WSDL2Constants.MEP_URI_OUT_IN); |
| } |
| //REVIEW: There are several other MEP's, such as: OUT_ONLY, IN_OPTIONAL_OUT, OUT_IN, OUT_OPTIONAL_IN, ROBUST_OUT_ONLY, |
| // ROBUST_IN_ONLY |
| // Determine how these MEP's should be handled, if at all |
| } catch (Exception e) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("clientAxisOprErr"),e); |
| } |
| |
| newAxisOperation.setName(determineOperationQName(seiMethod)); |
| newAxisOperation.setSoapAction(this.getAction()); |
| |
| //************************************************************************************* |
| //NOTE: assumption here is that all info. need to generate the actions will have to come |
| // from annotations (or default values) |
| //************************************************************************************* |
| |
| String messageExchangePattern = newAxisOperation.getMessageExchangePattern(); |
| String operationName = newAxisOperation.getName().getLocalPart(); |
| String targetNS = getEndpointInterfaceDescriptionImpl().getTargetNamespace(); |
| String portTypeName = getEndpointInterfaceDescriptionImpl().getPortType().getLocalPart(); |
| |
| //We don't have a name at this point, shouldn't matter if we have the MEP. |
| //On the client the input and output actions are reversed. |
| String inputName = null; |
| String inputAction = getOutputAction(); |
| |
| //If we still don't have an action then fall back to the Default Action Pattern. |
| if (inputAction == null || inputAction.length() == 0) { |
| inputAction = |
| WSDL11ActionHelper.getInputActionFromStringInformation( messageExchangePattern, |
| targetNS, |
| portTypeName, |
| operationName, |
| inputName); |
| } |
| |
| ArrayList inputActions = new ArrayList(); |
| inputActions.add(inputAction); |
| newAxisOperation.setWsamappingList(inputActions); |
| |
| //Map the action to the operation on the actual axisService |
| //TODO: Determine whether this should be done at a higher level in the |
| // description hierarchy |
| getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl(). |
| getAxisService().mapActionToOperation(inputAction, newAxisOperation); |
| |
| //set the OUTPUT ACTION |
| |
| //We don't have a name at this point, shouldn't matter if we have the MEP |
| //On the client the input and output actions are reversed. |
| String outputName = null; |
| String outputAction = getInputAction(); |
| |
| if (outputAction == null || outputAction.length() == 0) { |
| outputAction = |
| WSDL11ActionHelper.getOutputActionFromStringInformation( messageExchangePattern, |
| targetNS, |
| portTypeName, |
| operationName, |
| outputName); |
| } |
| |
| newAxisOperation.setOutputAction(outputAction); |
| |
| setFaultActions(newAxisOperation, operationName, targetNS, portTypeName); |
| |
| getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl(). |
| getAxisService().addOperation(newAxisOperation); |
| |
| return newAxisOperation; |
| } |
| |
| /** |
| * Create an AxisOperation for this Operation. Note that the ParameterDescriptions must |
| * be created before calling this method since, for a DOC/LIT/BARE (aka UNWRAPPED) message, the |
| * ParamaterDescription is used to setup the AxisMessage correctly for use in SOAP Body-based |
| * dispatching on incoming DOC/LIT/BARE messages. |
| */ |
| private AxisOperation createAxisOperation() { |
| AxisOperation newAxisOperation = null; |
| try { |
| if (isOneWay()) { |
| newAxisOperation = AxisOperationFactory |
| .getOperationDescription(WSDL2Constants.MEP_URI_IN_ONLY); |
| } else { |
| newAxisOperation = |
| AxisOperationFactory.getOperationDescription(WSDL2Constants.MEP_URI_IN_OUT); |
| } |
| //TODO: There are several other MEP's, such as: OUT_ONLY, IN_OPTIONAL_OUT, OUT_IN, OUT_OPTIONAL_IN, ROBUST_OUT_ONLY, |
| // ROBUST_IN_ONLY |
| // Determine how these MEP's should be handled, if at all |
| } catch (Exception e) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("clientAxisOprErr"), e); |
| } |
| |
| newAxisOperation.setName(determineOperationQName(this.methodComposite)); |
| newAxisOperation.setSoapAction(this.getAction()); |
| |
| //************************************************************************************* |
| //NOTE: assumption here is that all info. need to generate the actions will have to come |
| // from annotations (or default values) |
| //************************************************************************************* |
| |
| String messageExchangePattern = newAxisOperation.getMessageExchangePattern(); |
| String operationName = newAxisOperation.getName().getLocalPart(); |
| String targetNS = getEndpointInterfaceDescriptionImpl().getTargetNamespace(); |
| String portTypeName = getEndpointInterfaceDescriptionImpl().getPortType().getLocalPart(); |
| |
| //We don't have a name at this point, shouldn't matter if we have the MEP |
| String inputName = null; |
| String inputAction = getInputAction(); |
| |
| //If we don't have an action then fall back to the Default Action Pattern. |
| if (inputAction == null || inputAction.length() == 0) { |
| inputAction = |
| WSDL11ActionHelper.getInputActionFromStringInformation(messageExchangePattern, |
| targetNS, |
| portTypeName, |
| operationName, |
| inputName); |
| } |
| |
| ArrayList inputActions = new ArrayList(); |
| inputActions.add(inputAction); |
| newAxisOperation.setWsamappingList(inputActions); |
| |
| //Map the action to the operation on the actual axisService |
| //TODO: Determine whether this should be done at a higher level in the |
| // description hierarchy |
| getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl(). |
| getAxisService().mapActionToOperation(inputAction, newAxisOperation); |
| |
| //set the OUTPUT ACTION |
| |
| //We don't have a name at this point, shouldn't matter if we have the MEP |
| String outputName = null; |
| String outputAction = getOutputAction(); |
| |
| //If we don't have an action then fall back to the Default Action Pattern. |
| if (outputAction == null || outputAction.length() == 0) { |
| outputAction = |
| WSDL11ActionHelper.getOutputActionFromStringInformation(messageExchangePattern, |
| targetNS, |
| portTypeName, |
| operationName, |
| outputName); |
| } |
| |
| newAxisOperation.setOutputAction(outputAction); |
| |
| //Set the FAULT ACTION |
| setFaultActions(newAxisOperation, operationName, targetNS, portTypeName); |
| |
| // If this is a DOC/LIT/BARE operation, then set the QName of the input AxisMessage to the |
| // part for the first IN or IN/OUT non-header parameter. If there are no parameters, then don't set |
| // anything. The AxisMessage name is used to do SOAP-body based routing of DOC/LIT/BARE |
| // incoming messages. |
| if (getSoapBindingStyle() == javax.jws.soap.SOAPBinding.Style.DOCUMENT |
| && getSoapBindingUse() == javax.jws.soap.SOAPBinding.Use.LITERAL |
| && getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle.BARE) |
| { |
| ParameterDescription[] paramDescs = getParameterDescriptions(); |
| if (paramDescs != null && paramDescs.length > 0) { |
| for (ParameterDescription paramDesc : paramDescs) { |
| WebParam.Mode paramMode = paramDesc.getMode(); |
| if (!paramDesc.isHeader() |
| && (paramMode == WebParam.Mode.IN || paramMode == WebParam.Mode.INOUT)) |
| { |
| // We've found the first IN or INOUT non-header parameter, so set the AxisMessage |
| // QName based on this parameter then break out of the loop. |
| AxisMessage axisMessage = |
| newAxisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE); |
| String elementName = paramDesc.getParameterName(); |
| String partNamespace = paramDesc.getTargetNamespace(); |
| if (log.isDebugEnabled()) { |
| log.debug("Setting up annotation based Doc/Lit/Bare operation: " + |
| newAxisOperation.getName() |
| + "; axisMessage: " + axisMessage + "; name: " |
| + elementName + "; partTNS: " + partNamespace); |
| } |
| if (axisMessage == null) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("createAxisOprErr1")); |
| } else if (DescriptionUtils.isEmpty(partNamespace)) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("createAxisOprErr2")); |
| } else if (DescriptionUtils.isEmpty(elementName)) { |
| throw ExceptionFactory.makeWebServiceException(Messages.getMessage("createAxisOprErr3")); |
| } else { |
| QName partQName = new QName(partNamespace, elementName); |
| if(log.isDebugEnabled()) { |
| log.debug("Setting AxisMessage element QName for bare mapping: " + |
| partQName); |
| } |
| axisMessage.setElementQName(partQName); |
| |
| getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl() |
| .getAxisService() |
| .addMessageElementQNameToOperationMapping(partQName, newAxisOperation); |
| } |
| break; |
| } |
| } |
| } |
| } |
| return newAxisOperation; |
| } |
| |
| private void setFaultActions(AxisOperation newAxisOperation, |
| String operationName, |
| String targetNS, |
| String portTypeName) { |
| // Walk the fault information |
| FaultDescription[] faultDescs = getFaultDescriptions(); |
| |
| //Generate fault actions according to the Default Action Pattern. |
| if (faultDescs != null) { |
| for (FaultDescription faultDesc : faultDescs) { |
| |
| AxisMessage faultMessage = new AxisMessage(); |
| String faultName = faultDesc.getName(); |
| faultMessage.setName(faultName); |
| |
| String faultAction = |
| WSDL11ActionHelper.getFaultActionFromStringInformation( targetNS, |
| portTypeName, |
| operationName, |
| faultMessage.getName()); |
| |
| newAxisOperation.addFaultAction(faultDesc.getExceptionClassName(), faultAction); |
| newAxisOperation.setFaultMessages(faultMessage); |
| } |
| } |
| |
| //Override the fault actions based on any FaultAction annotations that are defined. |
| FaultAction[] faultActions = getFaultActions(); |
| |
| if (faultActions != null) { |
| for (FaultAction faultAction : faultActions) { |
| |
| String className = null; |
| |
| if(faultAction instanceof FaultActionAnnot |
| && |
| ((FaultActionAnnot) faultAction).classNameString() != null) { |
| className = ((FaultActionAnnot) faultAction).classNameString(); |
| } |
| else if(faultAction.className() != null) { |
| className = faultAction.className().getName(); |
| } |
| |
| if(className != null) { |
| if(log.isDebugEnabled()) { |
| log.debug("Looking for FaultDescription for class: " + className + |
| " from @FaultAction annotation"); |
| } |
| FaultDescription faultDesc = resolveFaultByExceptionName(className); |
| if (faultDesc != null) { |
| newAxisOperation.addFaultAction(className, faultAction.value()); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Adds the AxisOperation corresponding to this OperationDescription to the AxisService if it |
| * isn't already there. It also addes the AxisOperation to any other routing mechanisms for |
| * that AxisService: - For Doc/Lit/Bare operations it is added to the |
| * MessageElementQNameToOperationMapping |
| * |
| * @param axisService |
| */ |
| void addToAxisService(AxisService axisService) { |
| AxisOperation newAxisOperation = getAxisOperation(); |
| QName axisOpQName = newAxisOperation.getName(); |
| AxisOperation axisOperation = axisService.getOperation(axisOpQName); |
| if (axisOperation == null) { |
| axisService.addOperation(newAxisOperation); |
| // For a Doc/Lit/Bare operation, we also need to add the element mapping |
| } |
| if (getSoapBindingStyle() == javax.jws.soap.SOAPBinding.Style.DOCUMENT |
| && getSoapBindingUse() == javax.jws.soap.SOAPBinding.Use.LITERAL |
| && getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle |
| .BARE) { |
| AxisMessage axisMessage = |
| null; |
| if (axisOperation!=null) { |
| axisMessage = axisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE); |
| } else { |
| axisMessage = newAxisOperation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE); |
| } |
| if (axisMessage != null) { |
| QName elementQName = axisMessage.getElementQName(); |
| if (!DescriptionUtils.isEmpty(elementQName) && |
| axisService.getOperationByMessageElementQName(elementQName) == null) { |
| axisService.addMessageElementQNameToOperationMapping(elementQName, |
| newAxisOperation); |
| } |
| } |
| } |
| } |
| |
| void setSEIMethod(Method method) { |
| if (seiMethod != null) { |
| throw ExceptionFactory.makeWebServiceException( |
| new UnsupportedOperationException(Messages.getMessage("seiMethodErr"))); |
| } else { |
| seiMethod = method; |
| webMethodAnnotation = (WebMethod) |
| getAnnotation(seiMethod, WebMethod.class); |
| parameterDescriptions = createParameterDescriptions(); |
| faultDescriptions = createFaultDescriptions(); |
| isListType = ConverterUtils.hasXmlListAnnotation(seiMethod.getAnnotations()); |
| } |
| // Register understood headers on axisOperation |
| registerMustUnderstandHeaders(); |
| } |
| |
| public EndpointInterfaceDescription getEndpointInterfaceDescription() { |
| return parentEndpointInterfaceDescription; |
| } |
| |
| public EndpointInterfaceDescriptionImpl getEndpointInterfaceDescriptionImpl() { |
| return (EndpointInterfaceDescriptionImpl)parentEndpointInterfaceDescription; |
| } |
| |
| public AxisOperation getAxisOperation() { |
| // Note that only the sync operations, and not the JAX-WS async client versions of an |
| // operation, will have an AxisOperation associated with it. For those async operations, |
| // get the AxisOperation associated with the sync method and return that. |
| if (axisOperation == null) { |
| OperationDescription opDesc = getSyncOperation(); |
| if (opDesc != null && opDesc != this) { |
| return getSyncOperation().getAxisOperation(); |
| } |
| } |
| |
| return axisOperation; |
| } |
| |
| public QName getName() { |
| return operationQName; |
| } |
| |
| // Java-related getters |
| public String getJavaMethodName() { |
| String returnString = null; |
| |
| if (!isDBC()) { |
| if (seiMethod != null) { |
| returnString = seiMethod.getName(); |
| } |
| } else { |
| if (methodComposite != null) { |
| returnString = methodComposite.getMethodName(); |
| } |
| } |
| |
| return returnString; |
| } |
| |
| public String getJavaDeclaringClassName() { |
| if (!isDBC() && seiMethod != null) { |
| Class clazz = seiMethod.getDeclaringClass(); |
| return clazz.getCanonicalName(); |
| } else if (methodComposite != null) { |
| return methodComposite.getDeclaringClass(); |
| } |
| return null; |
| } |
| |
| public String[] getJavaParameters() { |
| |
| ArrayList<String> returnParameters = new ArrayList<String>(); |
| |
| if (!isDBC()) { |
| if (seiMethod != null) { |
| Class[] paramaters = seiMethod.getParameterTypes(); |
| for (Class param : paramaters) { |
| returnParameters.add(param.getName()); |
| } |
| } |
| |
| } else { |
| if (methodComposite != null) { |
| |
| Iterator<ParameterDescriptionComposite> iter = |
| methodComposite.getParameterDescriptionCompositeList().iterator(); |
| while (iter.hasNext()) { |
| returnParameters.add(iter.next().getParameterType()); |
| } |
| } |
| } |
| |
| // TODO: This is different than the rest, which return null instead of an empty array |
| return returnParameters.toArray(new String[0]); |
| } |
| |
| /** |
| * Note this will return NULL unless the operation was built via introspection on the SEI. In |
| * other words, it will return null if the operation was built with WSDL. |
| * |
| * @return |
| */ |
| public Method getSEIMethod() { |
| return seiMethod; |
| } |
| |
| MethodDescriptionComposite getMethodDescriptionComposite() { |
| return methodComposite; |
| } |
| |
| private boolean isWrappedParameters() { |
| return getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED; |
| } |
| |
| private ParameterDescription[] createParameterDescriptions() { |
| |
| ArrayList<ParameterDescription> buildParameterList = new ArrayList<ParameterDescription>(); |
| |
| if (!isDBC()) { |
| Class[] parameters = seiMethod.getParameterTypes(); |
| Type[] paramaterTypes = seiMethod.getGenericParameterTypes(); |
| Annotation[][] annotations = seiMethod.getParameterAnnotations(); |
| |
| for (int i = 0; i < parameters.length; i++) { |
| ParameterDescription paramDesc = new ParameterDescriptionImpl(i, parameters[i], |
| paramaterTypes[i], |
| annotations[i], this); |
| buildParameterList.add(paramDesc); |
| } |
| |
| } else { |
| ParameterDescriptionComposite pdc = null; |
| Iterator<ParameterDescriptionComposite> iter = |
| methodComposite.getParameterDescriptionCompositeList().iterator(); |
| |
| for (int i = 0; i < methodComposite.getParameterDescriptionCompositeList().size(); i++) |
| { |
| ParameterDescription paramDesc = |
| new ParameterDescriptionImpl(i, |
| methodComposite.getParameterDescriptionComposite( |
| i), |
| this); |
| buildParameterList.add(paramDesc); |
| } |
| } |
| |
| return buildParameterList.toArray(new ParameterDescription[buildParameterList.size()]); |
| |
| } |
| |
| private FaultDescription[] createFaultDescriptions() { |
| |
| ArrayList<FaultDescription> buildFaultList = new ArrayList<FaultDescription>(); |
| |
| if (!isDBC()) { |
| // get exceptions this method "throws" |
| Class[] webFaultClasses = seiMethod.getExceptionTypes(); |
| |
| for (Class wfClass : webFaultClasses) { |
| // according to JAXWS 3.7, the @WebFault annotation is only used for customizations, |
| // so we'll add all declared exceptions |
| WebFault wfanno = null; |
| for (Annotation anno : wfClass.getAnnotations()) { |
| if (anno.annotationType() == WebFault.class) { |
| wfanno = (WebFault)anno; |
| } |
| } |
| buildFaultList.add(new FaultDescriptionImpl(wfClass, wfanno, this)); |
| } |
| } else { |
| // TODO do I care about methodComposite like the paramDescription does? |
| //Call FaultDescriptionImpl for all non-generic exceptions...Need to check a |
| // a couple of things |
| // 1. If this is a generic exception, ignore it |
| // 2. If this is not a generic exception, then find it in the DBC Map |
| // If not found in map, then throw not found exception |
| //3. Pass the validated WebFault dbc and possibly the classImpl dbc to FaultDescription |
| //4. Possibly set AxisOperation.setFaultMessages array...or something like that |
| |
| String[] webFaultClassNames = methodComposite.getExceptions(); |
| |
| HashMap<String, DescriptionBuilderComposite> dbcMap = |
| getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl() |
| .getServiceDescriptionImpl().getDBCMap(); |
| |
| if (webFaultClassNames != null) { |
| for (String wfClassName : webFaultClassNames) { |
| // Try to find this exception class in the dbc list. If we can't find it |
| // then just assume that its a generic exception. |
| |
| DescriptionBuilderComposite faultDBC = dbcMap.get(wfClassName); |
| |
| if (faultDBC != null) { |
| // JAXWS 3.7 does not require @WebFault annotation |
| // We found a valid exception composite thats annotated |
| buildFaultList.add(new FaultDescriptionImpl(faultDBC, this)); |
| } |
| |
| } |
| } |
| } |
| |
| return buildFaultList.toArray(new FaultDescription[0]); |
| } |
| |
| // ===================================== |
| // ANNOTATION: WebMethod |
| // ===================================== |
| public WebMethod getAnnoWebMethod() { |
| if (webMethodAnnotation == null) { |
| if (isDBC() && methodComposite != null) { |
| webMethodAnnotation = methodComposite.getWebMethodAnnot(); |
| } else if (!isDBC() && seiMethod != null) { |
| webMethodAnnotation = (WebMethod) getAnnotation(seiMethod, WebMethod.class); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get WebMethod annotation"); |
| } |
| } |
| } |
| return webMethodAnnotation; |
| } |
| |
| static QName determineOperationQName(Method javaMethod) { |
| return new QName(determineOperationName(javaMethod)); |
| } |
| |
| public static QName determineOperationQName(MethodDescriptionComposite mdc) { |
| return new QName(determineOperationName(mdc)); |
| } |
| |
| private static String determineOperationName(Method javaMethod) { |
| |
| String operationName = null; |
| if (javaMethod == null) { |
| return null; |
| } |
| |
| WebMethod wmAnnotation = (WebMethod) getAnnotation(javaMethod,WebMethod.class); |
| // Per JSR-181 MR Sec 4.2 "Annotation: javax.jws.WebMethod" pg 17, |
| // if @WebMethod specifies and operation name, use that. Otherwise |
| // default is the Java method name |
| if (wmAnnotation != null && !DescriptionUtils.isEmpty(wmAnnotation.operationName())) { |
| operationName = wmAnnotation.operationName(); |
| } else { |
| operationName = javaMethod.getName(); |
| } |
| |
| return operationName; |
| } |
| |
| //TODO: For now, we are overriding the above method only because it is static, these should |
| //be combined at some point |
| private static String determineOperationName(MethodDescriptionComposite mdc) { |
| String operationName = null; |
| |
| if (mdc == null) { |
| return null; |
| } |
| WebMethod wmAnnotation = mdc.getWebMethodAnnot(); |
| if (wmAnnotation != null && !DescriptionUtils.isEmpty(wmAnnotation.operationName())) { |
| operationName = wmAnnotation.operationName(); |
| } else { |
| operationName = mdc.getMethodName(); |
| } |
| |
| return operationName; |
| } |
| |
| public String getOperationName() { |
| return getAnnoWebMethodOperationName(); |
| } |
| |
| public String getAnnoWebMethodOperationName() { |
| if (webMethodOperationName == null) { |
| if (!isDBC() && seiMethod != null) { |
| webMethodOperationName = determineOperationName(seiMethod); |
| } else if (methodComposite != null) { |
| webMethodOperationName = determineOperationName(methodComposite); |
| } |
| } |
| return webMethodOperationName; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.axis2.jaxws.description.OperationDescription#getSyncOperation() |
| */ |
| public OperationDescription getSyncOperation() { |
| |
| if (syncOperationDescription != null) { |
| // No need to do anything; the sync operation has already been set and will be |
| // returned below |
| } else if (!isJAXWSAsyncClientMethod()) { |
| // The current OpDesc is not an async operation. Cache it, then return it below. |
| syncOperationDescription = this; |
| } else { |
| // We haven't found a sync opdesc for this operation yet, so try again. See the |
| // comments in the interface declaration for this method on why this might occur. |
| OperationDescription opDesc = null; |
| |
| String webMethodAnnoName = getOperationName(); |
| String javaMethodName = getJavaMethodName(); |
| if (webMethodAnnoName != null && webMethodAnnoName.length() > 0 && |
| webMethodAnnoName != javaMethodName) { |
| EndpointInterfaceDescription eid = getEndpointInterfaceDescription(); |
| if (eid != null) { |
| //searching for opDesc of sync operation. |
| OperationDescription[] ods = null; |
| ods = eid.getOperationForJavaMethod(webMethodAnnoName); |
| if (ods != null) { |
| for (OperationDescription od : ods) { |
| if (od.getJavaMethodName().equals(webMethodAnnoName) |
| && !od.isJAXWSAsyncClientMethod()) { |
| opDesc = od; |
| break; |
| } |
| } |
| } |
| } |
| } |
| // Note that opDesc might still be null |
| syncOperationDescription = opDesc; |
| } |
| return syncOperationDescription; |
| } |
| |
| public String getAction() { |
| return getAnnoWebMethodAction(); |
| } |
| |
| public String getAnnoWebMethodAction() { |
| if (webMethodAction == null) { |
| if (getAnnoWebMethod() != null && |
| !DescriptionUtils.isEmpty(getAnnoWebMethod().action())) { |
| webMethodAction = getAnnoWebMethod().action(); |
| } else { |
| webMethodAction = WebMethod_Action_DEFAULT; |
| } |
| } |
| return webMethodAction; |
| } |
| |
| public boolean isExcluded() { |
| return getAnnoWebMethodExclude(); |
| } |
| |
| public boolean getAnnoWebMethodExclude() { |
| if (webMethodExclude == null) { |
| // TODO: Validation: if this attribute specified, no other elements allowed per JSR-181 MR Sec 4.2, pg 17 |
| // TODO: Validation: This element is not allowed on endpoint interfaces |
| // Unlike the elements with a String value, if the annotation is present, exclude will always |
| // return a usable value since it will default to FALSE if the element is not present. |
| if (getAnnoWebMethod() != null) { |
| webMethodExclude = new Boolean(getAnnoWebMethod().exclude()); |
| } else { |
| webMethodExclude = WebMethod_Exclude_DEFAULT; |
| } |
| } |
| |
| return webMethodExclude.booleanValue(); |
| } |
| |
| // ========================================== |
| // ANNOTATION: RequestWrapper |
| // ========================================== |
| public RequestWrapper getAnnoRequestWrapper() { |
| if (requestWrapperAnnotation == null) { |
| if (!isDBC() && seiMethod != null) { |
| requestWrapperAnnotation = (RequestWrapper) |
| getAnnotation(seiMethod,RequestWrapper.class); |
| } else if (isDBC() && methodComposite != null) { |
| requestWrapperAnnotation = methodComposite.getRequestWrapperAnnot(); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get RequestWrapper annotation"); |
| } |
| } |
| } |
| return requestWrapperAnnotation; |
| } |
| |
| public String getRequestWrapperLocalName() { |
| return getAnnoRequestWrapperLocalName(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoRequestWrapperLocalName() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (requestWrapperLocalName == null) { |
| if (getAnnoRequestWrapper() != null |
| && !DescriptionUtils.isEmpty(getAnnoRequestWrapper().localName())) { |
| requestWrapperLocalName = getAnnoRequestWrapper().localName(); |
| } else { |
| // The default value of localName is the value of operationQName as |
| // defined in the WebMethod annotation. [JAX-WS Sec. 7.3, p. 80] |
| requestWrapperLocalName = getAnnoWebMethodOperationName(); |
| } |
| } |
| return requestWrapperLocalName; |
| } |
| |
| public String getRequestWrapperTargetNamespace() { |
| return getAnnoRequestWrapperTargetNamespace(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoRequestWrapperTargetNamespace() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (requestWrapperTargetNamespace == null) { |
| if (getAnnoRequestWrapper() != null && |
| !DescriptionUtils.isEmpty(getAnnoRequestWrapper().targetNamespace())) { |
| requestWrapperTargetNamespace = getAnnoRequestWrapper().targetNamespace(); |
| } else { |
| // The default value for targetNamespace is the target namespace of the SEI. [JAX-WS Sec 7.3, p. 80] |
| requestWrapperTargetNamespace = |
| getEndpointInterfaceDescription().getTargetNamespace(); |
| } |
| } |
| return requestWrapperTargetNamespace; |
| } |
| |
| public String getRequestWrapperClassName() { |
| return getAnnoRequestWrapperClassName(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoRequestWrapperClassName() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (requestWrapperClassName == null) { |
| if (getAnnoRequestWrapper() != null && |
| !DescriptionUtils.isEmpty(getAnnoRequestWrapper().className())) { |
| requestWrapperClassName = getAnnoRequestWrapper().className(); |
| } else { |
| // There is no default for the RequestWrapper class name. |
| // In such cases the programming layer (JAXWS) may use a programming spec specific |
| // mechanism to find the class, build the class, or operate without the class. |
| requestWrapperClassName = null; |
| } |
| } |
| return requestWrapperClassName; |
| } |
| |
| // =========================================== |
| // ANNOTATION: ResponseWrapper |
| // =========================================== |
| public ResponseWrapper getAnnoResponseWrapper() { |
| if (responseWrapperAnnotation == null) { |
| if (!isDBC() && seiMethod != null) { |
| responseWrapperAnnotation = (ResponseWrapper) |
| getAnnotation(seiMethod,ResponseWrapper.class); |
| } else if (isDBC() && methodComposite != null) { |
| responseWrapperAnnotation = methodComposite.getResponseWrapperAnnot(); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get ResponseWrapper annotation"); |
| } |
| } |
| } |
| return responseWrapperAnnotation; |
| } |
| |
| public String getResponseWrapperLocalName() { |
| return getAnnoResponseWrapperLocalName(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoResponseWrapperLocalName() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (responseWrapperLocalName == null) { |
| if (getAnnoResponseWrapper() != null && |
| !DescriptionUtils.isEmpty(getAnnoResponseWrapper().localName())) { |
| responseWrapperLocalName = getAnnoResponseWrapper().localName(); |
| } else { |
| // The default value of localName is the value of operationQName as |
| // defined in the WebMethod annotation appended with "Response". [JAX-WS Sec. 7.4, p. 81] |
| responseWrapperLocalName = getAnnoWebMethodOperationName() + "Response"; |
| } |
| } |
| return responseWrapperLocalName; |
| } |
| |
| public String getResponseWrapperTargetNamespace() { |
| return getAnnoResponseWrapperTargetNamespace(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoResponseWrapperTargetNamespace() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (responseWrapperTargetNamespace == null) { |
| if (getAnnoResponseWrapper() != null && |
| !DescriptionUtils.isEmpty(getAnnoResponseWrapper().targetNamespace())) { |
| responseWrapperTargetNamespace = getAnnoResponseWrapper().targetNamespace(); |
| } else { |
| // The default value for targetNamespace is the target namespace of the SEI. [JAX-WS Sec 7.3, p. 80] |
| responseWrapperTargetNamespace = |
| getEndpointInterfaceDescription().getTargetNamespace(); |
| } |
| } |
| return responseWrapperTargetNamespace; |
| } |
| |
| public String getResponseWrapperClassName() { |
| return getAnnoResponseWrapperClassName(); |
| } |
| |
| /** |
| * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper |
| * value. For non-wrapped (i.e. bare) parameter style, returns null. |
| * |
| * @return |
| */ |
| public String getAnnoResponseWrapperClassName() { |
| if (!isWrappedParameters()) { |
| // A wrapper is only meaningful for wrapped parameters |
| return null; |
| } |
| if (responseWrapperClassName == null) { |
| if (getAnnoResponseWrapper() != null && |
| !DescriptionUtils.isEmpty(getAnnoResponseWrapper().className())) { |
| responseWrapperClassName = getAnnoResponseWrapper().className(); |
| } else { |
| // There is no default for the ResponseWrapper class name. |
| // In such cases the programming layer (JAXWS) may use a programming spec specific |
| // mechanism to find the class, build the class, or operate without the class. |
| responseWrapperClassName = null; |
| } |
| } |
| return responseWrapperClassName; |
| } |
| |
| // =========================================== |
| // ANNOTATION: WebFault |
| // =========================================== |
| |
| /* |
| * TODO some of the WebFault stuff should be moved to FaultDescription |
| */ |
| |
| /* |
| * TODO: this will need revisited. The problem is that a WebFault is not mapped 1:1 to an |
| * OperationDescription. We should do a better job caching the information. For now, I'm |
| * following the getWebParam() pattern. |
| * |
| * This is gonna get complicated. One other thing to consider is that a method (opdesc) may declare |
| * several types of exceptions it throws |
| * |
| */ |
| |
| public FaultDescription[] getFaultDescriptions() { |
| return faultDescriptions; |
| } |
| |
| public FaultDescription resolveFaultByExceptionName(String exceptionClassName) { |
| if (faultDescriptions != null) { |
| for (FaultDescription fd : faultDescriptions) { |
| if (exceptionClassName.equals(fd.getExceptionClassName())) |
| return fd; |
| } |
| } |
| return null; |
| } |
| |
| // =========================================== |
| // ANNOTATION: WebParam |
| // =========================================== |
| // Note that this annotation is handled by the ParameterDescripton. |
| // Methods are provided on OperationDescription as convenience methods. |
| public ParameterDescription[] getParameterDescriptions() { |
| return parameterDescriptions; |
| } |
| |
| public ParameterDescription getParameterDescription(String parameterName) { |
| // TODO: Validation: For BARE paramaterUse, only a single IN our INOUT paramater and a single output (either return or OUT or INOUT) is allowed |
| // Per JSR-224, Sec 3.6.2.2, pg 37 |
| ParameterDescription matchingParamDesc = null; |
| if (parameterName != null && !parameterName.equals("")) { |
| for (ParameterDescription paramDesc : parameterDescriptions) { |
| if (parameterName.equals(paramDesc.getParameterName())) { |
| matchingParamDesc = paramDesc; |
| break; |
| } |
| } |
| } |
| return matchingParamDesc; |
| } |
| |
| public ParameterDescription getParameterDescription(int parameterNumber) { |
| return parameterDescriptions[parameterNumber]; |
| } |
| |
| public String[] getParamNames() { |
| return getAnnoWebParamNames(); |
| } |
| |
| public String[] getAnnoWebParamNames() { |
| if (webParamNames == null) { |
| ArrayList<String> buildNames = new ArrayList<String>(); |
| ParameterDescription[] paramDescs = getParameterDescriptions(); |
| for (ParameterDescription currentParamDesc : paramDescs) { |
| buildNames.add(currentParamDesc.getParameterName()); |
| } |
| webParamNames = buildNames.toArray(new String[0]); |
| } |
| return webParamNames; |
| } |
| |
| public String[] getAnnoWebParamTargetNamespaces() { |
| if (webParamTargetNamespace == null) { |
| ArrayList<String> buildTargetNS = new ArrayList<String>(); |
| ParameterDescription[] paramDescs = getParameterDescriptions(); |
| for (ParameterDescription currentParamDesc : paramDescs) { |
| buildTargetNS.add(currentParamDesc.getTargetNamespace()); |
| } |
| webParamTargetNamespace = buildTargetNS.toArray(new String[0]); |
| } |
| return webParamTargetNamespace; |
| } |
| |
| public String getAnnoWebParamTargetNamespace(String name) { |
| String returnTargetNS = null; |
| ParameterDescription paramDesc = getParameterDescription(name); |
| if (paramDesc != null) { |
| returnTargetNS = paramDesc.getTargetNamespace(); |
| } |
| return returnTargetNS; |
| } |
| |
| |
| public Mode[] getAnnoWebParamModes() { |
| if (webParamMode == null) { |
| ArrayList<Mode> buildModes = new ArrayList<Mode>(); |
| ParameterDescription[] paramDescs = getParameterDescriptions(); |
| for (ParameterDescription currentParamDesc : paramDescs) { |
| buildModes.add(((ParameterDescriptionJava)currentParamDesc).getAnnoWebParamMode()); |
| } |
| webParamMode = buildModes.toArray(new Mode[0]); |
| } |
| return webParamMode; |
| } |
| |
| public boolean isAnnoWebParamHeader(String name) { |
| ParameterDescription paramDesc = getParameterDescription(name); |
| if (paramDesc != null) { |
| return paramDesc.isHeader(); |
| } |
| return false; |
| } |
| |
| // =========================================== |
| // ANNOTATION: WebResult |
| // =========================================== |
| public WebResult getAnnoWebResult() { |
| if (webResultAnnotation == null) { |
| if (!isDBC() && seiMethod != null) { |
| webResultAnnotation = (WebResult) |
| getAnnotation(seiMethod,WebResult.class); |
| } else if (methodComposite != null) { |
| webResultAnnotation = methodComposite.getWebResultAnnot(); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get WebResult annotation"); |
| } |
| } |
| } |
| return webResultAnnotation; |
| } |
| |
| public boolean isWebResultAnnotationSpecified() { |
| return getAnnoWebResult() != null; |
| } |
| |
| public boolean isOperationReturningResult() { |
| boolean isResult = false; |
| if (!isAnnoOneWay()) { |
| if (!isDBC() && seiMethod != null) { |
| if (seiMethod.getReturnType() != Void.TYPE) { |
| isResult = true; |
| } |
| } else if (methodComposite != null) { |
| if (!DescriptionUtils.isEmpty(methodComposite.getReturnType()) && |
| !methodComposite.getReturnType().equals("void")) |
| isResult = true; |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("No class to determine if result is returned"); |
| } |
| } |
| } |
| return isResult; |
| } |
| |
| public String getResultName() { |
| return getAnnoWebResultName(); |
| } |
| |
| public String getAnnoWebResultName() { |
| if (!isOperationReturningResult()) { |
| return null; |
| } |
| if (webResultName == null) { |
| if (getAnnoWebResult() != null && !DescriptionUtils.isEmpty(getAnnoWebResult().name())) |
| { |
| webResultName = getAnnoWebResult().name(); |
| } else if (getAnnoSoapBindingStyle() == SOAPBinding.Style.DOCUMENT |
| && getAnnoSoapBindingParameterStyle() == SOAPBinding.ParameterStyle.BARE) { |
| // Default for operation style DOCUMENT and paramater style BARE per JSR 181 MR Sec 4.5.1, pg 23 |
| webResultName = getAnnoWebMethodOperationName() + "Response"; |
| |
| } else { |
| // Defeault value is "return" per JSR-181 MR Sec. 4.5.1, p. 22 |
| webResultName = "return"; |
| } |
| } |
| return webResultName; |
| } |
| |
| public String getResultPartName() { |
| return getAnnoWebResultPartName(); |
| } |
| |
| public String getAnnoWebResultPartName() { |
| if (!isOperationReturningResult()) { |
| return null; |
| } |
| if (webResultPartName == null) { |
| if (getAnnoWebResult() != null && |
| !DescriptionUtils.isEmpty(getAnnoWebResult().partName())) { |
| webResultPartName = getAnnoWebResult().partName(); |
| } else { |
| // Default is the WebResult.name per JSR-181 MR Sec 4.5.1, pg 23 |
| webResultPartName = getAnnoWebResultName(); |
| } |
| } |
| return webResultPartName; |
| } |
| |
| public String getResultTargetNamespace() { |
| return getAnnoWebResultTargetNamespace(); |
| } |
| |
| public String getAnnoWebResultTargetNamespace() { |
| if (!isOperationReturningResult()) { |
| return null; |
| } |
| if (webResultTargetNamespace == null) { |
| if (getAnnoWebResult() != null && |
| !DescriptionUtils.isEmpty(getAnnoWebResult().targetNamespace())) { |
| webResultTargetNamespace = getAnnoWebResult().targetNamespace(); |
| } else if (getAnnoSoapBindingStyle() == SOAPBinding.Style.DOCUMENT |
| && getAnnoSoapBindingParameterStyle() == SOAPBinding.ParameterStyle.WRAPPED |
| && !getAnnoWebResultHeader()) { |
| // Default for operation style DOCUMENT and paramater style WRAPPED and the return value |
| // does not map to a header per JSR-181 MR Sec 4.5.1, pg 23-24 |
| webResultTargetNamespace = WebResult_TargetNamespace_DEFAULT; |
| } else { |
| // Default is the namespace from the WebService per JSR-181 MR Sec 4.5.1, pg 23-24 |
| webResultTargetNamespace = |
| ((EndpointDescriptionJava)getEndpointInterfaceDescription() |
| .getEndpointDescription()).getAnnoWebServiceTargetNamespace(); |
| } |
| |
| } |
| return webResultTargetNamespace; |
| } |
| |
| public boolean isResultHeader() { |
| return getAnnoWebResultHeader(); |
| } |
| |
| public boolean getAnnoWebResultHeader() { |
| if (!isOperationReturningResult()) { |
| return false; |
| } |
| if (webResultHeader == null) { |
| if (getAnnoWebResult() != null) { |
| // Unlike the elements with a String value, if the annotation is present, exclude will always |
| // return a usable value since it will default to FALSE if the element is not present. |
| webResultHeader = new Boolean(getAnnoWebResult().header()); |
| } else { |
| webResultHeader = WebResult_Header_DEFAULT; |
| } |
| } |
| return webResultHeader.booleanValue(); |
| } |
| |
| // =========================================== |
| // ANNOTATION: SOAPBinding |
| // =========================================== |
| public SOAPBinding getAnnoSoapBinding() { |
| // TODO: VALIDATION: Only style of DOCUMENT allowed on Method annotation; remember to check the Type's style setting also |
| // JSR-181 Sec 4.7 p. 28 |
| if (soapBindingAnnotation == null) { |
| if (!isDBC() && seiMethod != null) { |
| soapBindingAnnotation = (SOAPBinding) |
| getAnnotation(seiMethod,SOAPBinding.class); |
| } else if (isDBC() && methodComposite != null) { |
| soapBindingAnnotation = methodComposite.getSoapBindingAnnot(); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get SOAP Binding annotation"); |
| } |
| } |
| } |
| return soapBindingAnnotation; |
| } |
| |
| public javax.jws.soap.SOAPBinding.Style getSoapBindingStyle() { |
| return getAnnoSoapBindingStyle(); |
| } |
| |
| public javax.jws.soap.SOAPBinding.Style getAnnoSoapBindingStyle() { |
| if (soapBindingStyle == null) { |
| if (getAnnoSoapBinding() != null && getAnnoSoapBinding().style() != null) { |
| soapBindingStyle = getAnnoSoapBinding().style(); |
| } else { |
| // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value. |
| soapBindingStyle = getEndpointInterfaceDescription().getSoapBindingStyle(); |
| } |
| } |
| return soapBindingStyle; |
| } |
| |
| public javax.jws.soap.SOAPBinding.Use getSoapBindingUse() { |
| return getAnnoSoapBindingUse(); |
| } |
| |
| public javax.jws.soap.SOAPBinding.Use getAnnoSoapBindingUse() { |
| if (soapBindingUse == null) { |
| if (getAnnoSoapBinding() != null && getAnnoSoapBinding().use() != null) { |
| soapBindingUse = getAnnoSoapBinding().use(); |
| } else { |
| // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value. |
| soapBindingUse = getEndpointInterfaceDescription().getSoapBindingUse(); |
| } |
| } |
| return soapBindingUse; |
| } |
| |
| public javax.jws.soap.SOAPBinding.ParameterStyle getSoapBindingParameterStyle() { |
| return getAnnoSoapBindingParameterStyle(); |
| } |
| |
| public javax.jws.soap.SOAPBinding.ParameterStyle getAnnoSoapBindingParameterStyle() { |
| if (soapBindingParameterStyle == null) { |
| if (getAnnoSoapBinding() != null && getAnnoSoapBinding().parameterStyle() != null) { |
| soapBindingParameterStyle = getAnnoSoapBinding().parameterStyle(); |
| } else { |
| // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value. |
| soapBindingParameterStyle = |
| getEndpointInterfaceDescription().getSoapBindingParameterStyle(); |
| } |
| } |
| return soapBindingParameterStyle; |
| } |
| |
| // =========================================== |
| // ANNOTATION: Action |
| // =========================================== |
| public Action getAnnoAction() { |
| if (actionAnnotation == null) { |
| if (!isDBC() && seiMethod != null) { |
| actionAnnotation = (Action) getAnnotation(seiMethod, Action.class); |
| } |
| else if (methodComposite != null) { |
| actionAnnotation = methodComposite.getActionAnnot(); |
| } |
| else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get Action annotation."); |
| } |
| } |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("getAnnoAction: " + actionAnnotation); |
| } |
| |
| return actionAnnotation; |
| } |
| |
| private String getInputAction() { |
| String inputAction = null; |
| Action action = getAnnoAction(); |
| |
| if (action != null) { |
| inputAction = action.input(); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("getInputAction: " + inputAction); |
| } |
| |
| return inputAction; |
| } |
| |
| private String getOutputAction() { |
| String outputAction = null; |
| Action action = getAnnoAction(); |
| |
| if (action != null) { |
| outputAction = action.output(); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("getOutputAction: " + outputAction); |
| } |
| |
| return outputAction; |
| } |
| |
| private FaultAction[] getFaultActions() { |
| FaultAction[] faultActions = null; |
| Action action = getAnnoAction(); |
| |
| if (action != null) { |
| faultActions = action.fault(); |
| } |
| |
| if (log.isDebugEnabled()) { |
| log.debug("getFaultActions: " + faultActions); |
| } |
| |
| return faultActions; |
| } |
| |
| // =========================================== |
| // ANNOTATION: OneWay |
| // =========================================== |
| public Oneway getAnnoOneway() { |
| if (onewayAnnotation == null) { |
| // Get the onew-way annotation from either the method composite (server-side) |
| // or from the SEI method (client-side). |
| if (isDBC() && methodComposite != null) { |
| if (methodComposite.isOneWay()) { |
| onewayAnnotation = OneWayAnnot.createOneWayAnnotImpl(); |
| } |
| } else if (!isDBC() && seiMethod != null) { |
| onewayAnnotation = (Oneway) getAnnotation(seiMethod,Oneway.class); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get OneWay annotation"); |
| } |
| } |
| } |
| return onewayAnnotation; |
| } |
| |
| public boolean isOneWay() { |
| return isAnnoOneWay(); |
| } |
| |
| public boolean isAnnoOneWay() { |
| if (onewayIsOneway == null) { |
| if (getAnnoOneway() != null) { |
| // The presence of the annotation indicates the method is oneway |
| onewayIsOneway = new Boolean(true); |
| } else { |
| // If the annotation is not present, the default is this is NOT a One Way method |
| onewayIsOneway = new Boolean(false); |
| } |
| } |
| return onewayIsOneway.booleanValue(); |
| } |
| |
| private boolean isDBC() { |
| if (methodComposite != null) |
| return true; |
| else |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.axis2.jaxws.description.OperationDescription#getResultType() |
| */ |
| public Class getResultType() { |
| Class returnClass = null; |
| if (!isDBC() && getSEIMethod() != null) { |
| Method seiMethod = this.getSEIMethod(); |
| returnClass = seiMethod.getReturnType(); |
| } else if (methodComposite != null) { |
| returnClass = methodComposite.getReturnTypeClass(); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Unable to get result type from null class"); |
| } |
| } |
| return returnClass; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.apache.axis2.jaxws.description.OperationDescription#getResultActualType() |
| */ |
| public Class getResultActualType() { |
| if(resultActualTypeClazz == null) { |
| resultActualTypeClazz = findResultActualType(); |
| } |
| return resultActualTypeClazz; |
| } |
| |
| public Class findResultActualType() { |
| // TODO: Fix this! it isn't doing the right thing for DBC as noted below with FIXME comments |
| // This is used to marshall the rsp on the service (dbc) and demarshall on the client (reflection) |
| // But we shouldn't get an async OpDesc on the service since getDispatchableOperation(QN) removes them. |
| |
| Class returnType = getResultType(); |
| if (returnType == null) { |
| return null; |
| } |
| if (isJAXWSAsyncClientMethod()) { |
| //pooling implementation |
| if (Response.class == returnType) { |
| if (!isDBC()) { |
| Type type = seiMethod.getGenericReturnType(); |
| ParameterizedType pType = (ParameterizedType)type; |
| Type aType = pType.getActualTypeArguments()[0]; |
| if (aType != null && ParameterizedType.class.isInstance(aType)) { |
| return (Class)((ParameterizedType)aType).getRawType(); |
| } |
| return (Class)aType; |
| } else { |
| // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side |
| // yet; the client is all Java Reflection. On the Service side, the Async methods are not used. |
| // This needs to return T for Response<T>, or List for Response<List<T>>> |
| return returnType; |
| } |
| } |
| //Callback Implementation |
| else { |
| // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side |
| // yet; the client is all Java Reflection. On the Service side, the Async methods are not used. |
| // This needs to find and return T for AsyncHandler<T>, or List for AsyncHandler<List<T>>> |
| Type[] type = getGenericParameterTypes(); |
| Class parameters[] = getParameterTypes(); |
| int i = 0; |
| for (Class param : parameters) { |
| if (AsyncHandler.class.isAssignableFrom(param)) { |
| ParameterizedType pType = (ParameterizedType)type[i]; |
| Type aType = pType.getActualTypeArguments()[0]; |
| if (aType != null && ParameterizedType.class.isInstance(aType)) { |
| return (Class)((ParameterizedType)aType).getRawType(); |
| } |
| return (Class)aType; |
| } |
| i++; |
| } |
| } |
| } |
| |
| return returnType; |
| } |
| |
| |
| private Type[] getGenericParameterTypes() { |
| if (isDBC()) { |
| // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side |
| // yet; the client is all Java Reflection. On the Service side, the Async methods are not used. |
| // And this method is only used to parse out the JAX-WS Async parameter types to find |
| // AsyncHandler<T>. The problem with the code that was removed is that a Type can not be |
| // instantiated, so we can't new up a Type inside the PDC. |
| throw ExceptionFactory.makeWebServiceException(new UnsupportedOperationException(Messages.getMessage("genParamTypesErr"))); |
| // Type [] type = new Type[parameterDescriptions.length]; |
| // for (int i=0; i < parameterDescriptions.length; i++){ |
| // type[i] = ((ParameterDescriptionImpl) parameterDescriptions[i]).getParameterActualGenericType(); |
| // } |
| // return type; |
| } else { |
| Type [] type = seiMethod.getGenericParameterTypes(); |
| return type; |
| } |
| } |
| |
| private Class[] getParameterTypes() { |
| if (isDBC()) { |
| Class [] parameters = new Class[parameterDescriptions.length]; |
| for (int i = 0; i < parameterDescriptions.length; i++) { |
| parameters[i] = parameterDescriptions[i].getParameterType(); |
| } |
| return parameters; |
| } else { |
| Class [] parameters = seiMethod.getParameterTypes(); |
| return parameters; |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.apache.axis2.jaxws.description.OperationDescription#isJAXWSAsyncClientMethod() |
| */ |
| public boolean isJAXWSAsyncClientMethod() { |
| boolean answer = false; |
| String methodName = null; |
| String returnTypeName = null; |
| if (isDBC()) { |
| methodName = getMethodDescriptionComposite().getMethodName(); |
| returnTypeName = getMethodDescriptionComposite().getReturnType(); |
| } else { |
| Method method = this.getSEIMethod(); |
| if (method != null) { |
| methodName = method.getName(); |
| returnTypeName = method.getReturnType().getName(); |
| } |
| } |
| if (methodName != null && returnTypeName != null) { |
| answer = (returnTypeName.contains(Response.class.getName()) || |
| returnTypeName.contains(Future.class.getName())); |
| } |
| if (log.isDebugEnabled()) { |
| log.debug("Method = " + methodName); |
| log.debug("Return Type = " + returnTypeName); |
| log.debug("Is client async = " + answer); |
| } |
| return answer; |
| } |
| |
| /** |
| * Return the Service Implementation method for this operation IFF it has been set by a previous |
| * call to getMethodFromServiceImpl(Class serviceImplClass). Otherwise a null is returned. |
| * |
| * @return |
| */ |
| private Method getMethodFromServiceImpl() { |
| return serviceImplMethod; |
| |
| } |
| |
| public Method getMethodFromServiceImpl(Class serviceImpl) { |
| |
| // TODO: This doesn't support overloaded methods in the service impl This is |
| // DIFFERENT than overloaded WSDL operations (which aren't supported). We |
| // MUST support overloaded service impl methods as long as they have different |
| // wsdl operation names. For example: |
| // ServiceImple Class SEI Class |
| // @WebMethod.name = Foo1 |
| // void foo() void foo() |
| // @WebMethod.name = Foo2 |
| // void foo(int) void foo(int) |
| // @WebMethod.name = Foo3 |
| // void foo(String) void foo(String) |
| // |
| // There will be two OpDescs, Foo1 and Foo2; the incoming wsdl operation will correctly identify |
| // which OpDesc. However, to return the correct service impl method, we need to compare the |
| // signatures, not just the method names. |
| if (!serviceImplMethodFound) { |
| Method[] methods = serviceImpl.getMethods(); |
| String opDescMethodName = getJavaMethodName(); |
| ParameterDescription[] paramDesc = getParameterDescriptions(); |
| // TODO: As noted above, a full signature is necessary, not just number of params |
| int numberOfParams = 0; |
| if (paramDesc != null) { |
| numberOfParams = paramDesc.length; |
| } |
| |
| // Loop through all the methods on the service impl and find the method that maps |
| // to this OperationDescripton |
| for (Method checkMethod : methods) { |
| if (checkMethod.getName().equals(opDescMethodName)) { |
| Class[] methodParams = checkMethod.getParameterTypes(); |
| // TODO: As noted above, a full signature is necessary, not just number of params |
| if (methodParams.length == numberOfParams) { |
| if (paramTypesMatch(paramDesc, methodParams)) { |
| serviceImplMethod = checkMethod; |
| break; |
| } |
| } |
| } |
| } |
| serviceImplMethodFound = true; |
| } |
| return serviceImplMethod; |
| } |
| |
| /** |
| * This method will compare the types of the parameters in a <code>ParameterDescription</code> |
| * vs. the type of the arguments in the parameters of a <code>Method</code>. |
| * |
| * @param paramDescs - <code>ParameterDescription</code>[] |
| * @param methodParams - <code>Class</code>[] |
| * @return - <code>boolean</code> |
| */ |
| private boolean paramTypesMatch(ParameterDescription[] paramDescs, Class[] |
| methodParams) { |
| for (int i = 0; i < paramDescs.length; i++) { |
| String mParamType = methodParams[i].getName(); |
| String pdType = getPDType(paramDescs[i]); |
| if (mParamType == null || !mParamType.equals(pdType)) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * This will get a <code>String</code> representing the parameter class of a |
| * <code>ParameterDescription</code>. |
| * |
| * @param pd - <code>ParameterDescrition</code> |
| * @return - <code>String</code> |
| */ |
| private String getPDType(ParameterDescription pd) { |
| String type = null; |
| if (pd.getParameterType() != null) { |
| type = pd.getParameterType().getName(); |
| } else if (pd.getParameterActualType() != null) { |
| type = pd.getParameterActualType().getName(); |
| } |
| return type; |
| } |
| |
| public OperationRuntimeDescription getOperationRuntimeDesc(String name) { |
| // TODO Add toString support |
| return runtimeDescMap.get(name); |
| } |
| |
| public void setOperationRuntimeDesc(OperationRuntimeDescription ord) { |
| // TODO Add toString support |
| runtimeDescMap.put(ord.getKey(), ord); |
| } |
| |
| public boolean isListType() { |
| return isListType; |
| } |
| |
| /** |
| * This method will return the namespace for the BindingInput that this operation |
| * specifies. It will first look for a namespace on the WSDL Binding object and then |
| * default to the web service's target namespace. |
| */ |
| public String getBindingInputNamespace() { |
| String tns = null; |
| Binding binding = |
| this.getEndpointInterfaceDescriptionImpl() |
| .getEndpointDescriptionImpl() |
| .getWSDLBinding(); |
| if (binding != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Found WSDL binding"); |
| } |
| // this call does not support overloaded WSDL operations as it |
| // does not specify the name of the input and output messages |
| BindingOperation bindingOp = |
| binding.getBindingOperation(getOperationName(), null, null); |
| if (bindingOp != null && bindingOp.getBindingInput() != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Found WSDL binding operation and input"); |
| } |
| tns = getBindingNamespace(bindingOp.getBindingInput()); |
| if (tns != null && log.isDebugEnabled()) { |
| log.debug("For operation: " + bindingOp.getName() |
| + " returning the following namespace for input message" |
| + " from WSDL: " + tns); |
| } |
| } |
| } |
| if (tns == null) { |
| tns = getEndpointInterfaceDescription().getTargetNamespace(); |
| if (log.isDebugEnabled()) { |
| log.debug("For binding input returning @WebService.targetNamespace: " + tns); |
| } |
| } |
| return tns; |
| } |
| |
| /** |
| * This method will return the namespace for the BindingOutput that this operation |
| * specifies. It will first look for a namespace on the WSDL Binding object and then |
| * default to the web service's target namespace. |
| */ |
| public String getBindingOutputNamespace() { |
| String tns = null; |
| Binding binding = |
| this.getEndpointInterfaceDescriptionImpl() |
| .getEndpointDescriptionImpl() |
| .getWSDLBinding(); |
| if (binding != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Found WSDL binding"); |
| } |
| // this call does not support overloaded WSDL operations as it |
| // does not specify the name of the input and output messages |
| BindingOperation bindingOp = |
| binding.getBindingOperation(getOperationName(), null, null); |
| if (bindingOp != null && bindingOp.getBindingOutput() != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Found WSDL binding operation and output"); |
| } |
| tns = getBindingNamespace(bindingOp.getBindingOutput()); |
| if (tns != null && log.isDebugEnabled()) { |
| log.debug("For operation: " + bindingOp.getName() |
| + " returning the following namespace for output message" |
| + " from WSDL: " + tns); |
| } |
| } |
| } |
| if (tns == null) { |
| tns = getEndpointInterfaceDescription().getTargetNamespace(); |
| if (log.isDebugEnabled()) { |
| log.debug("For binding output returning @WebService.targetNamespace: " + tns); |
| } |
| } |
| return tns; |
| } |
| |
| |
| /** |
| * This method will retrieve the namespace that is specified by the BindingInput or |
| * BindingOutput object. |
| */ |
| private String getBindingNamespace(AttributeExtensible opInfo) { |
| if (opInfo instanceof BindingInput) { |
| BindingInput input = (BindingInput) opInfo; |
| return DescriptionUtils.getNamespaceFromSOAPElement(input.getExtensibilityElements()); |
| } else if (opInfo instanceof BindingOutput) { |
| BindingOutput output = (BindingOutput) opInfo; |
| return DescriptionUtils.getNamespaceFromSOAPElement(output.getExtensibilityElements()); |
| } |
| return null; |
| } |
| |
| public AttachmentDescription getResultAttachmentDescription() { |
| String partName = this.getResultPartName(); |
| if (partName != null) { |
| if (log.isDebugEnabled()) { |
| log.debug("Returning result AttachmentDescription for partName: " + partName); |
| } |
| return partAttachmentMap.get(partName); |
| } |
| if (log.isDebugEnabled()) { |
| log.debug("Did not find result AttachmentDescription for partName: " + partName); |
| } |
| return null; |
| } |
| |
| /** |
| * This method will drive the building of AttachmentDescription objects for the |
| * operation input/output messages in the WSDL. |
| * |
| */ |
| private void buildAttachmentInformation() { |
| if (log.isDebugEnabled()) { |
| log.debug("Start buildAttachmentInformation"); |
| } |
| // Only building attachment info if we find a full WSDL |
| if (this.getEndpointInterfaceDescriptionImpl() |
| .getEndpointDescriptionImpl() |
| .isWSDLFullySpecified()) { |
| if (log.isDebugEnabled()) { |
| log.debug("A full WSDL is available. Query the WSDL binding for the " + |
| "AttachmentDescription information."); |
| } |
| DescriptionUtils.getAttachmentFromBinding(this, |
| this.getEndpointInterfaceDescriptionImpl() |
| .getEndpointDescriptionImpl() |
| .getWSDLBinding()); |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("The WSDL is not available. Looking for @WebService wsdlLocation."); |
| } |
| |
| // Try getting a WSDL |
| String wsdlLocation = this.getEndpointInterfaceDescriptionImpl(). |
| getEndpointDescriptionImpl(). |
| getAnnoWebServiceWSDLLocation(); |
| |
| if (wsdlLocation == null || wsdlLocation.length() == 0) { |
| if (log.isDebugEnabled()) { |
| log.debug("@WebService wsdlLocation is not specified. " + |
| "Processing continues without AttachmentDescription information"); |
| } |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("@WebService wsdlLocation is " + wsdlLocation); |
| } |
| |
| Definition def = null; |
| WSDL4JWrapper wsdl4j = null; |
| try { |
| File file = new File(wsdlLocation); |
| URL url = file.toURL(); |
| wsdl4j = new WSDL4JWrapper(url, true, 2); // In this context, limit the wsdl memory |
| def = wsdl4j.getDefinition(); |
| } catch (Throwable t) { |
| if (log.isDebugEnabled()) { |
| log.debug("Error occurred while loading WSDL. " + |
| "Procesing continues without AttachmentDescription " + |
| "information. " + t); |
| } |
| } |
| if (def != null) { |
| // Set the WSDL on the server |
| this.getEndpointInterfaceDescriptionImpl().getEndpointDescriptionImpl(). |
| getServiceDescriptionImpl().setWsdlWrapper(wsdl4j); |
| if (log.isDebugEnabled()) { |
| log.debug("WSDL Definition is loaded. Get the WSDL Binding."); |
| } |
| |
| Binding binding = this.getEndpointInterfaceDescriptionImpl(). |
| getEndpointDescriptionImpl().getWSDLBinding(); |
| |
| if (binding == null) { |
| if (log.isDebugEnabled()) { |
| log.debug("WSDL Binding was not found for serviceName=" + |
| this.getEndpointInterfaceDescription(). |
| getEndpointDescription().getServiceQName() + |
| " and portName=" + |
| this.getEndpointInterfaceDescription(). |
| getEndpointDescription().getPortQName()); |
| } |
| } else { |
| if (log.isDebugEnabled()) { |
| log.debug("Query Binding for AttachmentDescription Information"); |
| } |
| DescriptionUtils.getAttachmentFromBinding(this, binding); |
| } |
| } |
| } |
| |
| } |
| if (log.isDebugEnabled()) { |
| log.debug("End buildAttachmentInformation"); |
| } |
| } |
| |
| /** |
| * This will return an AttachmentDescription based on a part name. |
| */ |
| public AttachmentDescription getPartAttachmentDescription(String partName) { |
| return partAttachmentMap.get(partName); |
| } |
| |
| public void addPartAttachmentDescription(String partName, AttachmentDescription attachmentDesc) { |
| partAttachmentMap.put(partName, attachmentDesc); |
| } |
| |
| public boolean hasRequestSwaRefAttachments() { |
| return hasRequestSwaRefAttachments; |
| } |
| |
| public void setHasRequestSwaRefAttachments(boolean b) { |
| hasRequestSwaRefAttachments = b; |
| } |
| |
| public boolean hasResponseSwaRefAttachments() { |
| return hasResponseSwaRefAttachments; |
| } |
| |
| public void setHasResponseSwaRefAttachments(boolean b) { |
| hasResponseSwaRefAttachments = b; |
| } |
| |
| public String toString() { |
| final String newline = "\n"; |
| final String sameline = "; "; |
| StringBuffer string = new StringBuffer(); |
| try { |
| string.append(super.toString()); |
| string.append(newline); |
| string.append("Name: " + getName()); |
| string.append(sameline); |
| string.append("Operation Name: " + getOperationName()); |
| string.append(sameline); |
| string.append("Action: " + getAction()); |
| // |
| string.append(newline); |
| string.append("Operation excluded: " + (isExcluded() == true)); |
| string.append(sameline); |
| string.append("Is oneway: " + (isOneWay() == true)); |
| string.append(sameline); |
| string.append("Is returning result: " + (isOperationReturningResult() == true)); |
| string.append(sameline); |
| string.append("Is result header: " + (isResultHeader() == true)); |
| string.append(sameline); |
| string.append("Is JAXWS Client Async method: " + (isJAXWSAsyncClientMethod() == true)); |
| // |
| string.append(newline); |
| string.append("SOAP Style: " + getSoapBindingStyle()); |
| string.append(sameline); |
| string.append("SOAP Use: " + getSoapBindingUse()); |
| string.append(sameline); |
| string.append("SOAP Paramater Style: " + getSoapBindingParameterStyle()); |
| // |
| string.append(newline); |
| string.append("Result name: " + getResultName()); |
| string.append(sameline); |
| string.append("Result part name: " + getResultPartName()); |
| string.append(sameline); |
| string.append("Result type: " + getResultType()); |
| string.append(sameline); |
| string.append("Result actual type: " + getResultActualType()); |
| if (getResultAttachmentDescription() != null) { |
| string.append(newline); |
| string.append(getResultAttachmentDescription().toString()); |
| } |
| // |
| string.append(newline); |
| string.append("Request Wrapper class: " + getRequestWrapperClassName()); |
| string.append(sameline); |
| string.append("Response Wrapper class: " + getResponseWrapperClassName()); |
| // |
| string.append(newline); |
| string.append("Java declaring class name: " + getJavaDeclaringClassName()); |
| string.append(newline); |
| string.append("Java method name: " + getJavaMethodName()); |
| string.append(newline); |
| string.append("Java paramaters: " + getJavaParameters()); |
| string.append(newline); |
| string.append("Service Implementation method: " + getMethodFromServiceImpl()); |
| string.append(newline); |
| string.append("Axis Operation: " + getAxisOperation()); |
| |
| string.append(newline); |
| ParameterDescription[] paramDescs = getParameterDescriptions(); |
| if (paramDescs != null && paramDescs.length > 0) { |
| string.append("Number of Parameter Descriptions: " + paramDescs.length); |
| for (ParameterDescription paramDesc : paramDescs) { |
| string.append(newline); |
| string.append("Parameter Description: " + paramDesc.toString()); |
| } |
| } else { |
| string.append("No Paramater Descriptions"); |
| } |
| |
| string.append(newline); |
| FaultDescription[] faultDescs = getFaultDescriptions(); |
| if (faultDescs != null && faultDescs.length > 0) { |
| string.append("Number of Fault Descriptions: " + faultDescs.length); |
| for (FaultDescription faultDesc : faultDescs) { |
| string.append(newline); |
| string.append("Fault Description: " + faultDesc.toString()); |
| } |
| } else { |
| string.append("No Fault Descriptions"); |
| } |
| |
| if(!partAttachmentMap.isEmpty()) { |
| string.append(newline); |
| string.append("Number of Attachment Descriptions: " + partAttachmentMap.size()); |
| string.append(newline); |
| Iterator<AttachmentDescription> adIter = partAttachmentMap.values().iterator(); |
| while(adIter.hasNext()) { |
| string.append(adIter.next().toString()); |
| string.append(newline); |
| } |
| } else { |
| string.append(newline); |
| string.append("No Attachment Descriptions"); |
| string.append(newline); |
| } |
| |
| string.append("RuntimeDescriptions:" + this.runtimeDescMap.size()); |
| string.append(newline); |
| for (OperationRuntimeDescription runtimeDesc : runtimeDescMap.values()) { |
| string.append(runtimeDesc.toString()); |
| string.append(newline); |
| } |
| } |
| catch (Throwable t) { |
| string.append(newline); |
| string.append("Complete debug information not currently available for " + |
| "OperationDescription"); |
| return string.toString(); |
| } |
| return string.toString(); |
| } |
| |
| /** |
| * Adds a list of SOAP header QNames that are understood by JAXWS for this operation to the |
| * AxisOperation. This will be used by Axis2 to verify that all headers marked as |
| * mustUnderstand have been or will be processed. |
| * |
| * Server side headers considered understood [JAXWS 2.0 Sec 10.2.1 page 117] |
| * - SEI method params that are in headers |
| * - Headers processed by application handlers (TBD) |
| * |
| * Client side headers considered understood: None |
| * |
| */ |
| private void registerMustUnderstandHeaders() { |
| |
| // REVIEW: If client side (return value, OUT or INOUT params) needs to be supported then |
| // this needs to process client and server differently. |
| |
| AxisOperation theAxisOperation = getAxisOperation(); |
| if (theAxisOperation == null) { |
| if (log.isDebugEnabled()) { |
| log.debug("The axis operation is null, so header QNames could not be registered. OpDesc = " + this); |
| } |
| return; |
| } |
| |
| // If any IN or INOUT parameters are in the header, then add their QNames to the list |
| ParameterDescription paramDescs[] = getParameterDescriptions(); |
| ArrayList understoodQNames = new ArrayList(); |
| if (paramDescs != null && paramDescs.length > 0) { |
| for (ParameterDescription paramDesc : paramDescs) { |
| if (paramDesc.isHeader() |
| && (paramDesc.getMode() == WebParam.Mode.IN |
| || paramDesc.getMode() == WebParam.Mode.INOUT)) { |
| QName headerQN = new QName(paramDesc.getTargetNamespace(), |
| paramDesc.getParameterName()); |
| understoodQNames.add(headerQN); |
| if (log.isDebugEnabled()) { |
| log.debug("OpDesc: understoodQName added to AxisOperation (if not null) " + headerQN); |
| } |
| } |
| } |
| } |
| |
| if (!understoodQNames.isEmpty()) { |
| Parameter headerQNParameter = new Parameter(OperationDescription.HEADER_PARAMETER_QNAMES, |
| understoodQNames); |
| try { |
| theAxisOperation.addParameter(headerQNParameter); |
| } catch (AxisFault e) { |
| log.warn(Messages.getMessage("regMUHeadersErr",theAxisOperation.getClass().getName()), e); |
| } |
| } |
| } |
| /** |
| * Get an annotation. This is wrappered to avoid a Java2Security violation. |
| * @param cls Class that contains annotation |
| * @param annotation Class of requrested Annotation |
| * @return annotation or null |
| */ |
| private static Annotation getAnnotation(final AnnotatedElement element, final Class annotation) { |
| return (Annotation) AccessController.doPrivileged(new PrivilegedAction() { |
| public Object run() { |
| return element.getAnnotation(annotation); |
| } |
| }); |
| } |
| } |