0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: */
0019:
0020: package org.apache.axis2.jaxws.description.impl;
0021:
0022: import org.apache.axis2.AxisFault;
0023: import org.apache.axis2.addressing.wsdl.WSDL11ActionHelper;
0024: import org.apache.axis2.description.AxisMessage;
0025: import org.apache.axis2.description.AxisOperation;
0026: import org.apache.axis2.description.AxisOperationFactory;
0027: import org.apache.axis2.description.AxisService;
0028: import org.apache.axis2.description.Parameter;
0029: import org.apache.axis2.description.WSDL2Constants;
0030: import org.apache.axis2.jaxws.ExceptionFactory;
0031: import org.apache.axis2.jaxws.description.AttachmentDescription;
0032: import org.apache.axis2.jaxws.description.AttachmentType;
0033: import org.apache.axis2.jaxws.description.EndpointDescriptionJava;
0034: import org.apache.axis2.jaxws.description.EndpointInterfaceDescription;
0035: import org.apache.axis2.jaxws.description.FaultDescription;
0036: import org.apache.axis2.jaxws.description.OperationDescription;
0037: import org.apache.axis2.jaxws.description.OperationDescriptionJava;
0038: import org.apache.axis2.jaxws.description.OperationDescriptionWSDL;
0039: import org.apache.axis2.jaxws.description.OperationRuntimeDescription;
0040: import org.apache.axis2.jaxws.description.ParameterDescription;
0041: import org.apache.axis2.jaxws.description.ParameterDescriptionJava;
0042: import org.apache.axis2.jaxws.description.builder.DescriptionBuilderComposite;
0043: import org.apache.axis2.jaxws.description.builder.MethodDescriptionComposite;
0044: import org.apache.axis2.jaxws.description.builder.OneWayAnnot;
0045: import org.apache.axis2.jaxws.description.builder.ParameterDescriptionComposite;
0046: import org.apache.axis2.jaxws.description.builder.converter.ConverterUtils;
0047: import org.apache.axis2.jaxws.util.WSDL4JWrapper;
0048: import org.apache.axis2.wsdl.WSDLConstants;
0049: import org.apache.commons.logging.Log;
0050: import org.apache.commons.logging.LogFactory;
0051:
0052: import javax.jws.Oneway;
0053: import javax.jws.WebMethod;
0054: import javax.jws.WebParam;
0055: import javax.jws.WebResult;
0056: import javax.jws.WebParam.Mode;
0057: import javax.jws.soap.SOAPBinding;
0058: import javax.wsdl.Binding;
0059: import javax.wsdl.BindingInput;
0060: import javax.wsdl.BindingOperation;
0061: import javax.wsdl.BindingOutput;
0062: import javax.wsdl.Definition;
0063: import javax.wsdl.extensions.AttributeExtensible;
0064: import javax.xml.bind.annotation.XmlList;
0065: import javax.xml.namespace.QName;
0066: import javax.xml.ws.AsyncHandler;
0067: import javax.xml.ws.RequestWrapper;
0068: import javax.xml.ws.Response;
0069: import javax.xml.ws.ResponseWrapper;
0070: import javax.xml.ws.WebFault;
0071:
0072: import java.io.File;
0073: import java.lang.annotation.Annotation;
0074: import java.lang.reflect.Method;
0075: import java.lang.reflect.ParameterizedType;
0076: import java.lang.reflect.Type;
0077: import java.net.URL;
0078: import java.util.ArrayList;
0079: import java.util.Collections;
0080: import java.util.HashMap;
0081: import java.util.Iterator;
0082: import java.util.Map;
0083: import java.util.concurrent.Future;
0084:
0085: /** @see ../OperationDescription */
0086: // TODO: Axis2 does not support overloaded operations, although EndpointInterfaceDescription.addOperation() does support overloading
0087: // of methods represented by OperationDescription classes. However, the AxisOperation contained in an OperationDescription
0088: // does NOT support overloaded methods.
0089: //
0090: // While overloading is not supported by WS-I, it IS supported by JAX-WS (p11).
0091: // Note that this requires support in Axis2; currently WSDL11ToAxisServiceBuilder.populateOperations does not
0092: // support overloaded methods in the WSDL; the operations are stored on AxisService as children in a HashMap with the wsdl
0093: // operation name as the key.
0094: // TODO: Need tests for all the "default" code paths in the annotation getters.
0095: // TODO: Need tests for each when annotation is not present where that is allowed by the spec.
0096: class OperationDescriptionImpl implements OperationDescription,
0097: OperationDescriptionJava, OperationDescriptionWSDL {
0098: private EndpointInterfaceDescription parentEndpointInterfaceDescription;
0099: private AxisOperation axisOperation;
0100: private QName operationQName;
0101: private Method seiMethod;
0102: private MethodDescriptionComposite methodComposite;
0103: private ParameterDescription[] parameterDescriptions;
0104: private FaultDescription[] faultDescriptions;
0105: private static final Log log = LogFactory
0106: .getLog(OperationDescriptionImpl.class);
0107: // ===========================================
0108: // ANNOTATION related information
0109: // ===========================================
0110:
0111: // ANNOTATION: @Oneway
0112: private Oneway onewayAnnotation;
0113: private Boolean onewayIsOneway;
0114:
0115: // ANNOTATION: @XmlList
0116: private boolean isListType = false;
0117:
0118: // ANNOTATION: @RequestWrapper
0119: private RequestWrapper requestWrapperAnnotation;
0120: private String requestWrapperTargetNamespace;
0121: private String requestWrapperLocalName;
0122: private String requestWrapperClassName;
0123:
0124: // ANNOTATION: @ResponseWrapper
0125: private ResponseWrapper responseWrapperAnnotation;
0126: private String responseWrapperLocalName;
0127: private String responseWrapperTargetNamespace;
0128: private String responseWrapperClassName;
0129:
0130: // ANNOTATION: @SOAPBinding
0131: // Note this is the Method-level annotation. See EndpointInterfaceDescription for the Type-level annotation
0132: // Also note this annotation is only allowed on methods if SOAPBinding.Style is DOCUMENT and if the method-level
0133: // annotation is absent, the behavior defined on the Type is used.
0134: // per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
0135: private SOAPBinding soapBindingAnnotation;
0136: // REVIEW: Should this be using the jaxws annotation values or should that be wrappered?
0137: private javax.jws.soap.SOAPBinding.Style soapBindingStyle;
0138: public static final javax.jws.soap.SOAPBinding.Style SoapBinding_Style_VALID = javax.jws.soap.SOAPBinding.Style.DOCUMENT;
0139: private javax.jws.soap.SOAPBinding.Use soapBindingUse;
0140: // Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
0141: public static final javax.jws.soap.SOAPBinding.Use SOAPBinding_Use_DEFAULT = javax.jws.soap.SOAPBinding.Use.LITERAL;
0142: private javax.jws.soap.SOAPBinding.ParameterStyle soapBindingParameterStyle;
0143: // Default value per JSR-181 MR Sec 4.7 "Annotation: javax.jws.soap.SOAPBinding" pg 28
0144: public static final javax.jws.soap.SOAPBinding.ParameterStyle SOAPBinding_ParameterStyle_DEFAULT = javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
0145:
0146: // ANNOTATION: @WebMethod
0147: private WebMethod webMethodAnnotation;
0148: private String webMethodOperationName;
0149: // Default value per JSR-181 MR Sec 4.2, pg 17
0150: public static final String WebMethod_Action_DEFAULT = "";
0151: private String webMethodAction;
0152: // Default value per JSR-181 MR sec 4.2, pg 17
0153: public static final Boolean WebMethod_Exclude_DEFAULT = new Boolean(
0154: false);
0155: private Boolean webMethodExclude;
0156:
0157: // ANNOTATION: @WebParam
0158: private String[] webParamNames;
0159: private Mode[] webParamMode;
0160: private String[] webParamTargetNamespace;
0161:
0162: // ANNOTATION: @WebResult
0163: private WebResult webResultAnnotation;
0164: private String webResultName;
0165: private String webResultPartName;
0166: // Default value per JSR-181 MR Sec 4.5.1, pg 23
0167: public static final String WebResult_TargetNamespace_DEFAULT = "";
0168: private String webResultTargetNamespace;
0169: // Default value per JSR-181 MR sec 4.5, pg 24
0170: public static final Boolean WebResult_Header_DEFAULT = new Boolean(
0171: false);
0172: private Boolean webResultHeader;
0173:
0174: // Web Result Attachment Description information
0175: private boolean _setAttachmentDesc = false;
0176: private AttachmentDescription attachmentDesc = null;
0177:
0178: private Method serviceImplMethod;
0179: private boolean serviceImplMethodFound = false;
0180: // For JAX-WS client async methods, this is the corresponding Sync method; for everything else,
0181: // this is "this".
0182: private OperationDescription syncOperationDescription = null;
0183: // RUNTIME INFORMATION
0184: Map<String, OperationRuntimeDescription> runtimeDescMap = Collections
0185: .synchronizedMap(new HashMap<String, OperationRuntimeDescription>());
0186: private Map<String, AttachmentDescription> partAttachmentMap;
0187:
0188: OperationDescriptionImpl(Method method,
0189: EndpointInterfaceDescription parent) {
0190: // TODO: Look for WebMethod anno; get name and action off of it
0191: parentEndpointInterfaceDescription = parent;
0192: partAttachmentMap = new HashMap<String, AttachmentDescription>();
0193: setSEIMethod(method);
0194: isListType = ConverterUtils.hasXmlListAnnotation(method
0195: .getAnnotations());
0196: // The operationQName is intentionally unqualified to be consistent with the remaining parts of the system.
0197: // Using a qualified name will cause breakage.
0198: // Don't do --> this.operationQName = new QName(parent.getTargetNamespace(), getOperationName());
0199: this .operationQName = new QName("", getOperationName());
0200: if (getEndpointInterfaceDescription().getEndpointDescription() != null) {
0201: if (!getEndpointInterfaceDescription()
0202: .getEndpointDescription().getServiceDescription()
0203: .isServerSide()) {
0204: axisOperation = createClientAxisOperation();
0205: }
0206: }
0207: buildAttachmentInformation();
0208: }
0209:
0210: OperationDescriptionImpl(AxisOperation operation,
0211: EndpointInterfaceDescription parent) {
0212: parentEndpointInterfaceDescription = parent;
0213: partAttachmentMap = new HashMap<String, AttachmentDescription>();
0214: axisOperation = operation;
0215: this .operationQName = axisOperation.getName();
0216: buildAttachmentInformation();
0217: }
0218:
0219: OperationDescriptionImpl(MethodDescriptionComposite mdc,
0220: EndpointInterfaceDescription parent,
0221: AxisOperation axisOperation) {
0222:
0223: parentEndpointInterfaceDescription = parent;
0224: partAttachmentMap = new HashMap<String, AttachmentDescription>();
0225: methodComposite = mdc;
0226: // The operationQName is intentionally unqualified to be consistent with the remaining parts of the system.
0227: // Using a qualified name will cause breakage.
0228: // Don't do --> this.operationQName = new QName(parent.getTargetNamespace(), getOperationName());
0229: this .operationQName = new QName("", getOperationName());
0230:
0231: webMethodAnnotation = methodComposite.getWebMethodAnnot();
0232:
0233: parameterDescriptions = createParameterDescriptions();
0234: faultDescriptions = createFaultDescriptions();
0235: isListType = mdc.isListType();
0236: buildAttachmentInformation();
0237:
0238: //If an AxisOperation was already created for us by populateService then just use that one
0239: //Otherwise, create it
0240: if (axisOperation != null) {
0241: this .axisOperation = axisOperation;
0242: } else {
0243: this .axisOperation = createAxisOperation();
0244: }
0245: // Register understood headers on axisOperation
0246: registerMustUnderstandHeaders();
0247: }
0248:
0249: /**
0250: * Create an AxisOperation for this Operation. Note that the ParameterDescriptions must
0251: * be created before calling this method since, for a DOC/LIT/BARE (aka UNWRAPPED) message, the
0252: * ParamaterDescription is used to setup the AxisMessage correctly for use in SOAP Body-based
0253: * dispatching on incoming DOC/LIT/BARE messages.
0254: */
0255: private AxisOperation createClientAxisOperation() {
0256: AxisOperation newAxisOperation = null;
0257: try {
0258: if (isOneWay()) {
0259: newAxisOperation = AxisOperationFactory
0260: .getOperationDescription(WSDL2Constants.MEP_URI_OUT_ONLY);
0261: } else {
0262: newAxisOperation = AxisOperationFactory
0263: .getOperationDescription(WSDL2Constants.MEP_URI_OUT_IN);
0264: }
0265: //TODO: There are several other MEP's, such as: OUT_ONLY, IN_OPTIONAL_OUT, OUT_IN, OUT_OPTIONAL_IN, ROBUST_OUT_ONLY,
0266: // ROBUST_IN_ONLY
0267: // Determine how these MEP's should be handled, if at all
0268: } catch (Exception e) {
0269: if (log.isDebugEnabled()) {
0270: log
0271: .debug(
0272: "Unable to build AxisOperation for OperationDescrition; caught exception.",
0273: e);
0274: }
0275: // TODO: NLS & RAS
0276: throw ExceptionFactory.makeWebServiceException(
0277: "Caught exception trying to create AxisOperation",
0278: e);
0279: }
0280:
0281: newAxisOperation.setName(determineOperationQName(seiMethod));
0282:
0283: getEndpointInterfaceDescriptionImpl()
0284: .getEndpointDescriptionImpl().getAxisService()
0285: .addOperation(newAxisOperation);
0286:
0287: return newAxisOperation;
0288: }
0289:
0290: /**
0291: * Create an AxisOperation for this Operation. Note that the ParameterDescriptions must
0292: * be created before calling this method since, for a DOC/LIT/BARE (aka UNWRAPPED) message, the
0293: * ParamaterDescription is used to setup the AxisMessage correctly for use in SOAP Body-based
0294: * dispatching on incoming DOC/LIT/BARE messages.
0295: */
0296: private AxisOperation createAxisOperation() {
0297: AxisOperation newAxisOperation = null;
0298: try {
0299: if (isOneWay()) {
0300: newAxisOperation = AxisOperationFactory
0301: .getOperationDescription(WSDL2Constants.MEP_URI_IN_ONLY);
0302: } else {
0303: newAxisOperation = AxisOperationFactory
0304: .getOperationDescription(WSDL2Constants.MEP_URI_IN_OUT);
0305: }
0306: //TODO: There are several other MEP's, such as: OUT_ONLY, IN_OPTIONAL_OUT, OUT_IN, OUT_OPTIONAL_IN, ROBUST_OUT_ONLY,
0307: // ROBUST_IN_ONLY
0308: // Determine how these MEP's should be handled, if at all
0309: } catch (Exception e) {
0310: if (log.isDebugEnabled()) {
0311: log
0312: .debug(
0313: "Unable to build AxisOperation for OperationDescrition; caught exception.",
0314: e);
0315: }
0316: // TODO: NLS & RAS
0317: throw ExceptionFactory.makeWebServiceException(
0318: "Caught exception trying to create AxisOperation",
0319: e);
0320: }
0321:
0322: newAxisOperation
0323: .setName(determineOperationQName(this .methodComposite));
0324: newAxisOperation.setSoapAction(this .getAction());
0325:
0326: //*************************************************************************************
0327: //NOTE: assumption here is that all info. need to generate the actions will have to come
0328: // from annotations (or default values)
0329: //*************************************************************************************
0330:
0331: String messageExchangePattern = newAxisOperation
0332: .getMessageExchangePattern();
0333: String targetNS = getEndpointInterfaceDescriptionImpl()
0334: .getTargetNamespace();
0335: String portTypeName = getEndpointInterfaceDescriptionImpl()
0336: .getEndpointDescriptionImpl().getName();
0337: ArrayList inputActions = new ArrayList();
0338:
0339: //We don't have a name at this point, shouldn't matter if we have the MEP
0340: //String inputName = newAxisOperation.getName().getLocalPart();
0341: String inputName = null;
0342: String inputAction = WSDL11ActionHelper
0343: .getInputActionFromStringInformation(
0344: messageExchangePattern, targetNS, portTypeName,
0345: newAxisOperation.getName().getLocalPart(),
0346: inputName);
0347:
0348: if (inputAction != null) {
0349: inputActions.add(inputAction);
0350: newAxisOperation.setWsamappingList(inputActions);
0351: }
0352:
0353: //Map the action to the operation on the actual axisService
0354: //TODO: Determine whether this should be done at a higher level in the
0355: // description hierarchy
0356: getEndpointInterfaceDescriptionImpl()
0357: .getEndpointDescriptionImpl().getAxisService()
0358: .mapActionToOperation(inputAction, newAxisOperation);
0359:
0360: //set the OUTPUT ACTION
0361:
0362: //We don't have a name at this point, shouldn't matter if we have the MEP
0363: //String outputName = newAxisOperation.getName().getLocalPart(); //REVIEW:
0364: String outputName = null;
0365: String outputAction = WSDL11ActionHelper
0366: .getOutputActionFromStringInformation(
0367: messageExchangePattern, targetNS, portTypeName,
0368: newAxisOperation.getName().getLocalPart(),
0369: outputName);
0370:
0371: if (outputAction != null) {
0372: newAxisOperation.setOutputAction(outputAction);
0373: }
0374:
0375: //Set the FAULT ACTION
0376: // Walk the fault information
0377: FaultDescription[] faultDescs = getFaultDescriptions();
0378: if (faultDescs != null) {
0379: for (int i = 0; i < faultDescs.length; i++) {
0380:
0381: AxisMessage faultMessage = new AxisMessage();
0382: String faultName = faultDescs[i].getName();
0383: faultMessage.setName(faultName);
0384:
0385: String faultAction = WSDL11ActionHelper
0386: .getFaultActionFromStringInformation(
0387: messageExchangePattern, portTypeName,
0388: newAxisOperation.getName()
0389: .getLocalPart(), faultMessage
0390: .getName());
0391:
0392: if (faultAction != null) {
0393: newAxisOperation.addFaultAction(faultMessage
0394: .getName(), faultAction);
0395: }
0396: newAxisOperation.setFaultMessages(faultMessage);
0397: }
0398: }
0399:
0400: //REVIEW: Determine if other axisOperation values may need to be set
0401: // Currently, the following values are being set on AxisOperation in
0402: // ServiceBuilder.populateService which we are not setting:
0403: // AxisOperation.setPolicyInclude()
0404: // AxisOperation.setWsamappingList()
0405: // AxisOperation.setOutputAction()
0406: // AxisOperation.addFaultAction()
0407: // AxisOperation.setFaultMessages()
0408:
0409: // If this is a DOC/LIT/BARE operation, then set the QName of the input AxisMessage to the
0410: // part for the first IN or IN/OUT non-header parameter. If there are no parameters, then don't set
0411: // anything. The AxisMessage name is used to do SOAP-body based routing of DOC/LIT/BARE
0412: // incoming messages.
0413: if (getSoapBindingStyle() == javax.jws.soap.SOAPBinding.Style.DOCUMENT
0414: && getSoapBindingUse() == javax.jws.soap.SOAPBinding.Use.LITERAL
0415: && getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle.BARE) {
0416: ParameterDescription[] paramDescs = getParameterDescriptions();
0417: if (paramDescs != null && paramDescs.length > 0) {
0418: for (ParameterDescription paramDesc : paramDescs) {
0419: WebParam.Mode paramMode = paramDesc.getMode();
0420: if (!paramDesc.isHeader()
0421: && (paramMode == WebParam.Mode.IN || paramMode == WebParam.Mode.INOUT)) {
0422: // We've found the first IN or INOUT non-header parameter, so set the AxisMessage
0423: // QName based on this parameter then break out of the loop.
0424: AxisMessage axisMessage = newAxisOperation
0425: .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
0426: String elementName = paramDesc
0427: .getParameterName();
0428: String partNamespace = paramDesc
0429: .getTargetNamespace();
0430: if (log.isDebugEnabled()) {
0431: log
0432: .debug("Setting up annotation based Doc/Lit/Bare operation: "
0433: + newAxisOperation
0434: .getName()
0435: + "; axisMessage: "
0436: + axisMessage
0437: + "; name: "
0438: + elementName
0439: + "; partTNS: "
0440: + partNamespace);
0441: }
0442: if (axisMessage == null) {
0443: // TODO: RAS & NLS
0444: throw ExceptionFactory
0445: .makeWebServiceException("Could not setup Doc/Lit/Bare operation because input message is null");
0446: } else if (DescriptionUtils
0447: .isEmpty(partNamespace)) {
0448: // TODO: RAS & NLS
0449: throw ExceptionFactory
0450: .makeWebServiceException("Could not setup Doc/Lit/Bare operation because part namespace is empty");
0451: } else if (DescriptionUtils
0452: .isEmpty(elementName)) {
0453: // TODO: RAS & NLS
0454: throw ExceptionFactory
0455: .makeWebServiceException("Could not setup Doc/Lit/Bare operation because name is empty");
0456: } else {
0457: QName partQName = new QName(partNamespace,
0458: elementName);
0459: if (log.isDebugEnabled()) {
0460: log
0461: .debug("Setting AxisMessage element QName for bare mapping: "
0462: + partQName);
0463: }
0464: axisMessage.setElementQName(partQName);
0465: }
0466: break;
0467: }
0468: }
0469: }
0470: }
0471: return newAxisOperation;
0472: }
0473:
0474: /**
0475: * Adds the AxisOperation corresponding to this OperationDescription to the AxisService if it
0476: * isn't already there. It also addes the AxisOperation to any other routing mechanisms for
0477: * that AxisService: - For Doc/Lit/Bare operations it is added to the
0478: * MessageElementQNameToOperationMapping
0479: *
0480: * @param axisService
0481: */
0482: void addToAxisService(AxisService axisService) {
0483: AxisOperation newAxisOperation = getAxisOperation();
0484: QName axisOpQName = newAxisOperation.getName();
0485: AxisOperation axisOperation = axisService
0486: .getOperation(axisOpQName);
0487: if (axisOperation == null) {
0488: axisService.addOperation(newAxisOperation);
0489: // For a Doc/Lit/Bare operation, we also need to add the element mapping
0490: }
0491: if (getSoapBindingStyle() == javax.jws.soap.SOAPBinding.Style.DOCUMENT
0492: && getSoapBindingUse() == javax.jws.soap.SOAPBinding.Use.LITERAL
0493: && getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle.BARE) {
0494: AxisMessage axisMessage = null;
0495: if (axisOperation != null) {
0496: axisMessage = axisOperation
0497: .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
0498: } else {
0499: axisMessage = newAxisOperation
0500: .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
0501: }
0502: if (axisMessage != null) {
0503: QName elementQName = axisMessage.getElementQName();
0504: if (!DescriptionUtils.isEmpty(elementQName)) {
0505: axisService
0506: .addMessageElementQNameToOperationMapping(
0507: elementQName, newAxisOperation);
0508: }
0509: }
0510: }
0511: }
0512:
0513: void setSEIMethod(Method method) {
0514: if (seiMethod != null) {
0515: // TODO: This is probably an error, but error processing logic is incorrect
0516: throw new UnsupportedOperationException(
0517: "Can not set an SEI method once it has been set.");
0518: } else {
0519: seiMethod = method;
0520: webMethodAnnotation = seiMethod
0521: .getAnnotation(WebMethod.class);
0522: parameterDescriptions = createParameterDescriptions();
0523: faultDescriptions = createFaultDescriptions();
0524: }
0525: // Register understood headers on axisOperation
0526: registerMustUnderstandHeaders();
0527: }
0528:
0529: public EndpointInterfaceDescription getEndpointInterfaceDescription() {
0530: return parentEndpointInterfaceDescription;
0531: }
0532:
0533: public EndpointInterfaceDescriptionImpl getEndpointInterfaceDescriptionImpl() {
0534: return (EndpointInterfaceDescriptionImpl) parentEndpointInterfaceDescription;
0535: }
0536:
0537: public AxisOperation getAxisOperation() {
0538: // Note that only the sync operations, and not the JAX-WS async client versions of an
0539: // operation, will have an AxisOperation associated with it. For those async operations,
0540: // get the AxisOperation associated with the sync method and return that.
0541: if (axisOperation == null) {
0542: OperationDescription opDesc = getSyncOperation();
0543: if (opDesc != null && opDesc != this ) {
0544: return getSyncOperation().getAxisOperation();
0545: }
0546: }
0547:
0548: return axisOperation;
0549: }
0550:
0551: public QName getName() {
0552: return operationQName;
0553: }
0554:
0555: // Java-related getters
0556: public String getJavaMethodName() {
0557: String returnString = null;
0558:
0559: if (!isDBC()) {
0560: if (seiMethod != null) {
0561: returnString = seiMethod.getName();
0562: }
0563: } else {
0564: if (methodComposite != null) {
0565: returnString = methodComposite.getMethodName();
0566: }
0567: }
0568:
0569: return returnString;
0570: }
0571:
0572: public String getJavaDeclaringClassName() {
0573: if (!isDBC() && seiMethod != null) {
0574: Class clazz = seiMethod.getDeclaringClass();
0575: return clazz.getCanonicalName();
0576: } else if (methodComposite != null) {
0577: return methodComposite.getDeclaringClass();
0578: }
0579: return null;
0580: }
0581:
0582: public String[] getJavaParameters() {
0583:
0584: ArrayList<String> returnParameters = new ArrayList<String>();
0585:
0586: if (!isDBC()) {
0587: if (seiMethod != null) {
0588: Class[] paramaters = seiMethod.getParameterTypes();
0589: for (Class param : paramaters) {
0590: returnParameters.add(param.getName());
0591: }
0592: }
0593:
0594: } else {
0595: if (methodComposite != null) {
0596:
0597: Iterator<ParameterDescriptionComposite> iter = methodComposite
0598: .getParameterDescriptionCompositeList()
0599: .iterator();
0600: while (iter.hasNext()) {
0601: returnParameters
0602: .add(iter.next().getParameterType());
0603: }
0604: }
0605: }
0606:
0607: // TODO: This is different than the rest, which return null instead of an empty array
0608: return returnParameters.toArray(new String[0]);
0609: }
0610:
0611: /**
0612: * Note this will return NULL unless the operation was built via introspection on the SEI. In
0613: * other words, it will return null if the operation was built with WSDL.
0614: *
0615: * @return
0616: */
0617: public Method getSEIMethod() {
0618: return seiMethod;
0619: }
0620:
0621: MethodDescriptionComposite getMethodDescriptionComposite() {
0622: return methodComposite;
0623: }
0624:
0625: private boolean isWrappedParameters() {
0626: return getSoapBindingParameterStyle() == javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
0627: }
0628:
0629: private ParameterDescription[] createParameterDescriptions() {
0630:
0631: ArrayList<ParameterDescription> buildParameterList = new ArrayList<ParameterDescription>();
0632:
0633: if (!isDBC()) {
0634: Class[] parameters = seiMethod.getParameterTypes();
0635: Type[] paramaterTypes = seiMethod
0636: .getGenericParameterTypes();
0637: Annotation[][] annotations = seiMethod
0638: .getParameterAnnotations();
0639:
0640: for (int i = 0; i < parameters.length; i++) {
0641: ParameterDescription paramDesc = new ParameterDescriptionImpl(
0642: i, parameters[i], paramaterTypes[i],
0643: annotations[i], this );
0644: buildParameterList.add(paramDesc);
0645: }
0646:
0647: } else {
0648: ParameterDescriptionComposite pdc = null;
0649: Iterator<ParameterDescriptionComposite> iter = methodComposite
0650: .getParameterDescriptionCompositeList().iterator();
0651:
0652: for (int i = 0; i < methodComposite
0653: .getParameterDescriptionCompositeList().size(); i++) {
0654: ParameterDescription paramDesc = new ParameterDescriptionImpl(
0655: i, methodComposite
0656: .getParameterDescriptionComposite(i),
0657: this );
0658: buildParameterList.add(paramDesc);
0659: }
0660: }
0661:
0662: return buildParameterList
0663: .toArray(new ParameterDescription[buildParameterList
0664: .size()]);
0665:
0666: }
0667:
0668: private FaultDescription[] createFaultDescriptions() {
0669:
0670: ArrayList<FaultDescription> buildFaultList = new ArrayList<FaultDescription>();
0671:
0672: if (!isDBC()) {
0673: // get exceptions this method "throws"
0674: Class[] webFaultClasses = seiMethod.getExceptionTypes();
0675:
0676: for (Class wfClass : webFaultClasses) {
0677: // according to JAXWS 3.7, the @WebFault annotation is only used for customizations,
0678: // so we'll add all declared exceptions
0679: WebFault wfanno = null;
0680: for (Annotation anno : wfClass.getAnnotations()) {
0681: if (anno.annotationType() == WebFault.class) {
0682: wfanno = (WebFault) anno;
0683: }
0684: }
0685: buildFaultList.add(new FaultDescriptionImpl(wfClass,
0686: wfanno, this ));
0687: }
0688: } else {
0689: // TODO do I care about methodComposite like the paramDescription does?
0690: //Call FaultDescriptionImpl for all non-generic exceptions...Need to check a
0691: // a couple of things
0692: // 1. If this is a generic exception, ignore it
0693: // 2. If this is not a generic exception, then find it in the DBC Map
0694: // If not found in map, then throw not found exception
0695: //3. Pass the validated WebFault dbc and possibly the classImpl dbc to FaultDescription
0696: //4. Possibly set AxisOperation.setFaultMessages array...or something like that
0697:
0698: String[] webFaultClassNames = methodComposite
0699: .getExceptions();
0700:
0701: HashMap<String, DescriptionBuilderComposite> dbcMap = getEndpointInterfaceDescriptionImpl()
0702: .getEndpointDescriptionImpl()
0703: .getServiceDescriptionImpl().getDBCMap();
0704:
0705: if (webFaultClassNames != null) {
0706: for (String wfClassName : webFaultClassNames) {
0707: // Try to find this exception class in the dbc list. If we can't find it
0708: // then just assume that its a generic exception.
0709:
0710: DescriptionBuilderComposite faultDBC = dbcMap
0711: .get(wfClassName);
0712:
0713: if (faultDBC != null) {
0714: // JAXWS 3.7 does not require @WebFault annotation
0715: // We found a valid exception composite thats annotated
0716: buildFaultList.add(new FaultDescriptionImpl(
0717: faultDBC, this ));
0718: }
0719:
0720: }
0721: }
0722: }
0723:
0724: return buildFaultList.toArray(new FaultDescription[0]);
0725: }
0726:
0727: // =====================================
0728: // ANNOTATION: WebMethod
0729: // =====================================
0730: public WebMethod getAnnoWebMethod() {
0731: return webMethodAnnotation;
0732: }
0733:
0734: static QName determineOperationQName(Method javaMethod) {
0735: return new QName(determineOperationName(javaMethod));
0736: }
0737:
0738: //TODO: For now, we are overriding the above method only because it is static, these should
0739: //be combined at some point
0740: public static QName determineOperationQName(
0741: MethodDescriptionComposite mdc) {
0742: return new QName(determineOperationName(mdc));
0743: }
0744:
0745: //TODO: Deprecate this after we use only DBC objects
0746: private static String determineOperationName(Method javaMethod) {
0747:
0748: String operationName = null;
0749: if (javaMethod == null) {
0750: return null;
0751: }
0752:
0753: WebMethod wmAnnotation = javaMethod
0754: .getAnnotation(WebMethod.class);
0755: // Per JSR-181 MR Sec 4.2 "Annotation: javax.jws.WebMethod" pg 17,
0756: // if @WebMethod specifies and operation name, use that. Otherwise
0757: // default is the Java method name
0758: if (wmAnnotation != null
0759: && !DescriptionUtils.isEmpty(wmAnnotation
0760: .operationName())) {
0761: operationName = wmAnnotation.operationName();
0762: } else {
0763: operationName = javaMethod.getName();
0764: }
0765:
0766: return operationName;
0767: }
0768:
0769: //TODO: For now, we are overriding the above method only because it is static, these should
0770: //be combined at some point
0771: private static String determineOperationName(
0772: MethodDescriptionComposite mdc) {
0773: String operationName = null;
0774:
0775: if (mdc == null) {
0776: return null;
0777: }
0778: WebMethod wmAnnotation = mdc.getWebMethodAnnot();
0779: if (wmAnnotation != null
0780: && !DescriptionUtils.isEmpty(wmAnnotation
0781: .operationName())) {
0782: operationName = wmAnnotation.operationName();
0783: } else {
0784: operationName = mdc.getMethodName();
0785: }
0786:
0787: return operationName;
0788: }
0789:
0790: public String getOperationName() {
0791: // REVIEW: WSDL/Anno merge
0792: return getAnnoWebMethodOperationName();
0793: }
0794:
0795: public String getAnnoWebMethodOperationName() {
0796: if (webMethodOperationName == null) {
0797: if (!isDBC() && seiMethod != null) {
0798: webMethodOperationName = determineOperationName(seiMethod);
0799: } else if (methodComposite != null) {
0800: webMethodOperationName = determineOperationName(methodComposite);
0801: }
0802: }
0803: return webMethodOperationName;
0804: }
0805:
0806: /* (non-Javadoc)
0807: * @see org.apache.axis2.jaxws.description.OperationDescription#getSyncOperation()
0808: */
0809: public OperationDescription getSyncOperation() {
0810:
0811: if (syncOperationDescription != null) {
0812: // No need to do anything; the sync operation has already been set and will be
0813: // returned below
0814: } else if (!isJAXWSAsyncClientMethod()) {
0815: // The current OpDesc is not an async operation. Cache it, then return it below.
0816: syncOperationDescription = this ;
0817: } else {
0818: // We haven't found a sync opdesc for this operation yet, so try again. See the
0819: // comments in the interface declaration for this method on why this might occur.
0820: OperationDescription opDesc = null;
0821:
0822: String webMethodAnnoName = getOperationName();
0823: String javaMethodName = getJavaMethodName();
0824: if (webMethodAnnoName != null
0825: && webMethodAnnoName.length() > 0
0826: && webMethodAnnoName != javaMethodName) {
0827: EndpointInterfaceDescription eid = getEndpointInterfaceDescription();
0828: if (eid != null) {
0829: //searching for opDesc of sync operation.
0830: OperationDescription[] ods = null;
0831: ods = eid
0832: .getOperationForJavaMethod(webMethodAnnoName);
0833: if (ods != null) {
0834: for (OperationDescription od : ods) {
0835: if (od.getJavaMethodName().equals(
0836: webMethodAnnoName)
0837: && !od.isJAXWSAsyncClientMethod()) {
0838: opDesc = od;
0839: break;
0840: }
0841: }
0842: }
0843: }
0844: }
0845: // Note that opDesc might still be null
0846: syncOperationDescription = opDesc;
0847: }
0848: return syncOperationDescription;
0849: }
0850:
0851: public String getAction() {
0852: // REVIEW: WSDL/Anno merge
0853: return getAnnoWebMethodAction();
0854: }
0855:
0856: public String getAnnoWebMethodAction() {
0857: if (webMethodAction == null) {
0858: if (getAnnoWebMethod() != null
0859: && !DescriptionUtils.isEmpty(getAnnoWebMethod()
0860: .action())) {
0861: webMethodAction = getAnnoWebMethod().action();
0862: } else {
0863: webMethodAction = WebMethod_Action_DEFAULT;
0864: }
0865: }
0866: return webMethodAction;
0867: }
0868:
0869: public boolean isExcluded() {
0870: // REVIEW: WSDL/Annotation merge
0871: return getAnnoWebMethodExclude();
0872: }
0873:
0874: public boolean getAnnoWebMethodExclude() {
0875: if (webMethodExclude == null) {
0876: // TODO: Validation: if this attribute specified, no other elements allowed per JSR-181 MR Sec 4.2, pg 17
0877: // TODO: Validation: This element is not allowed on endpoint interfaces
0878: // Unlike the elements with a String value, if the annotation is present, exclude will always
0879: // return a usable value since it will default to FALSE if the element is not present.
0880: if (getAnnoWebMethod() != null) {
0881: webMethodExclude = new Boolean(getAnnoWebMethod()
0882: .exclude());
0883: } else {
0884: webMethodExclude = WebMethod_Exclude_DEFAULT;
0885: }
0886: }
0887:
0888: return webMethodExclude.booleanValue();
0889: }
0890:
0891: // ==========================================
0892: // ANNOTATION: RequestWrapper
0893: // ==========================================
0894: public RequestWrapper getAnnoRequestWrapper() {
0895: if (requestWrapperAnnotation == null) {
0896: if (!isDBC() && seiMethod != null) {
0897: requestWrapperAnnotation = seiMethod
0898: .getAnnotation(RequestWrapper.class);
0899: } else if (isDBC() && methodComposite != null) {
0900: requestWrapperAnnotation = methodComposite
0901: .getRequestWrapperAnnot();
0902: } else {
0903: if (log.isDebugEnabled()) {
0904: log
0905: .debug("Unable to get RequestWrapper annotation");
0906: }
0907: }
0908: }
0909: return requestWrapperAnnotation;
0910: }
0911:
0912: public String getRequestWrapperLocalName() {
0913: // REVIEW: WSDL/Anno merge
0914: return getAnnoRequestWrapperLocalName();
0915: }
0916:
0917: /**
0918: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
0919: * value. For non-wrapped (i.e. bare) parameter style, returns null.
0920: *
0921: * @return
0922: */
0923: public String getAnnoRequestWrapperLocalName() {
0924: if (!isWrappedParameters()) {
0925: // A wrapper is only meaningful for wrapped parameters
0926: return null;
0927: }
0928: if (requestWrapperLocalName == null) {
0929: if (getAnnoRequestWrapper() != null
0930: && !DescriptionUtils
0931: .isEmpty(getAnnoRequestWrapper()
0932: .localName())) {
0933: requestWrapperLocalName = getAnnoRequestWrapper()
0934: .localName();
0935: } else {
0936: // The default value of localName is the value of operationQName as
0937: // defined in the WebMethod annotation. [JAX-WS Sec. 7.3, p. 80]
0938: requestWrapperLocalName = getAnnoWebMethodOperationName();
0939: }
0940: }
0941: return requestWrapperLocalName;
0942: }
0943:
0944: public String getRequestWrapperTargetNamespace() {
0945: // REVIEW: WSDL/Anno merge
0946: return getAnnoRequestWrapperTargetNamespace();
0947: }
0948:
0949: /**
0950: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
0951: * value. For non-wrapped (i.e. bare) parameter style, returns null.
0952: *
0953: * @return
0954: */
0955: public String getAnnoRequestWrapperTargetNamespace() {
0956: if (!isWrappedParameters()) {
0957: // A wrapper is only meaningful for wrapped parameters
0958: return null;
0959: }
0960: if (requestWrapperTargetNamespace == null) {
0961: if (getAnnoRequestWrapper() != null
0962: && !DescriptionUtils
0963: .isEmpty(getAnnoRequestWrapper()
0964: .targetNamespace())) {
0965: requestWrapperTargetNamespace = getAnnoRequestWrapper()
0966: .targetNamespace();
0967: } else {
0968: // The default value for targetNamespace is the target namespace of the SEI. [JAX-WS Sec 7.3, p. 80]
0969: requestWrapperTargetNamespace = getEndpointInterfaceDescription()
0970: .getTargetNamespace();
0971: }
0972: }
0973: return requestWrapperTargetNamespace;
0974: }
0975:
0976: public String getRequestWrapperClassName() {
0977: // REVIEW: WSDL/Anno merge
0978: return getAnnoRequestWrapperClassName();
0979: }
0980:
0981: /**
0982: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
0983: * value. For non-wrapped (i.e. bare) parameter style, returns null.
0984: *
0985: * @return
0986: */
0987: public String getAnnoRequestWrapperClassName() {
0988: if (!isWrappedParameters()) {
0989: // A wrapper is only meaningful for wrapped parameters
0990: return null;
0991: }
0992: if (requestWrapperClassName == null) {
0993: if (getAnnoRequestWrapper() != null
0994: && !DescriptionUtils
0995: .isEmpty(getAnnoRequestWrapper()
0996: .className())) {
0997: requestWrapperClassName = getAnnoRequestWrapper()
0998: .className();
0999: } else {
1000: // There is no default for the RequestWrapper class name.
1001: // In such cases the programming layer (JAXWS) may use a programming spec specific
1002: // mechanism to find the class, build the class, or operate without the class.
1003: requestWrapperClassName = null;
1004: }
1005: }
1006: return requestWrapperClassName;
1007: }
1008:
1009: // ===========================================
1010: // ANNOTATION: ResponseWrapper
1011: // ===========================================
1012: public ResponseWrapper getAnnoResponseWrapper() {
1013: if (responseWrapperAnnotation == null) {
1014: if (!isDBC() && seiMethod != null) {
1015: responseWrapperAnnotation = seiMethod
1016: .getAnnotation(ResponseWrapper.class);
1017: } else if (isDBC() && methodComposite != null) {
1018: responseWrapperAnnotation = methodComposite
1019: .getResponseWrapperAnnot();
1020: } else {
1021: if (log.isDebugEnabled()) {
1022: log
1023: .debug("Unable to get ResponseWrapper annotation");
1024: }
1025: }
1026: }
1027: return responseWrapperAnnotation;
1028: }
1029:
1030: public String getResponseWrapperLocalName() {
1031: return getAnnoResponseWrapperLocalName();
1032: }
1033:
1034: /**
1035: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
1036: * value. For non-wrapped (i.e. bare) parameter style, returns null.
1037: *
1038: * @return
1039: */
1040: public String getAnnoResponseWrapperLocalName() {
1041: if (!isWrappedParameters()) {
1042: // A wrapper is only meaningful for wrapped parameters
1043: return null;
1044: }
1045: if (responseWrapperLocalName == null) {
1046: if (getAnnoResponseWrapper() != null
1047: && !DescriptionUtils
1048: .isEmpty(getAnnoResponseWrapper()
1049: .localName())) {
1050: responseWrapperLocalName = getAnnoResponseWrapper()
1051: .localName();
1052: } else {
1053: // The default value of localName is the value of operationQName as
1054: // defined in the WebMethod annotation appended with "Response". [JAX-WS Sec. 7.4, p. 81]
1055: responseWrapperLocalName = getAnnoWebMethodOperationName()
1056: + "Response";
1057: }
1058: }
1059: return responseWrapperLocalName;
1060: }
1061:
1062: public String getResponseWrapperTargetNamespace() {
1063: // REVIEW: WSDL/Anno merge
1064: return getAnnoResponseWrapperTargetNamespace();
1065: }
1066:
1067: /**
1068: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
1069: * value. For non-wrapped (i.e. bare) parameter style, returns null.
1070: *
1071: * @return
1072: */
1073: public String getAnnoResponseWrapperTargetNamespace() {
1074: if (!isWrappedParameters()) {
1075: // A wrapper is only meaningful for wrapped parameters
1076: return null;
1077: }
1078: if (responseWrapperTargetNamespace == null) {
1079: if (getAnnoResponseWrapper() != null
1080: && !DescriptionUtils
1081: .isEmpty(getAnnoResponseWrapper()
1082: .targetNamespace())) {
1083: responseWrapperTargetNamespace = getAnnoResponseWrapper()
1084: .targetNamespace();
1085: } else {
1086: // The default value for targetNamespace is the target namespace of the SEI. [JAX-WS Sec 7.3, p. 80]
1087: // TODO: Implement getting the TNS from the SEI
1088: responseWrapperTargetNamespace = getEndpointInterfaceDescription()
1089: .getTargetNamespace();
1090: }
1091: }
1092: return responseWrapperTargetNamespace;
1093: }
1094:
1095: public String getResponseWrapperClassName() {
1096: // REVIEW: WSDL/Anno merge
1097: return getAnnoResponseWrapperClassName();
1098: }
1099:
1100: /**
1101: * For wrapped parameter style (based on the annotation and the WSDL), returns the wrapper
1102: * value. For non-wrapped (i.e. bare) parameter style, returns null.
1103: *
1104: * @return
1105: */
1106: public String getAnnoResponseWrapperClassName() {
1107: if (!isWrappedParameters()) {
1108: // A wrapper is only meaningful for wrapped parameters
1109: return null;
1110: }
1111: if (responseWrapperClassName == null) {
1112: if (getAnnoResponseWrapper() != null
1113: && !DescriptionUtils
1114: .isEmpty(getAnnoResponseWrapper()
1115: .className())) {
1116: responseWrapperClassName = getAnnoResponseWrapper()
1117: .className();
1118: } else {
1119: // There is no default for the ResponseWrapper class name.
1120: // In such cases the programming layer (JAXWS) may use a programming spec specific
1121: // mechanism to find the class, build the class, or operate without the class.
1122: responseWrapperClassName = null;
1123: }
1124: }
1125: return responseWrapperClassName;
1126: }
1127:
1128: // ===========================================
1129: // ANNOTATION: WebFault
1130: // ===========================================
1131:
1132: /*
1133: * TODO some of the WebFault stuff should be moved to FaultDescription
1134: */
1135:
1136: /*
1137: * TODO: this will need revisited. The problem is that a WebFault is not mapped 1:1 to an
1138: * OperationDescription. We should do a better job caching the information. For now, I'm
1139: * following the getWebParam() pattern.
1140: *
1141: * This is gonna get complicated. One other thing to consider is that a method (opdesc) may declare
1142: * several types of exceptions it throws
1143: *
1144: */
1145:
1146: public FaultDescription[] getFaultDescriptions() {
1147: return faultDescriptions;
1148: }
1149:
1150: public FaultDescription resolveFaultByExceptionName(
1151: String exceptionClassName) {
1152: if (faultDescriptions != null) {
1153: for (FaultDescription fd : faultDescriptions) {
1154: if (exceptionClassName.equals(fd
1155: .getExceptionClassName()))
1156: return fd;
1157: }
1158: }
1159: return null;
1160: }
1161:
1162: // ===========================================
1163: // ANNOTATION: WebParam
1164: // ===========================================
1165: // Note that this annotation is handled by the ParameterDescripton.
1166: // Methods are provided on OperationDescription as convenience methods.
1167: public ParameterDescription[] getParameterDescriptions() {
1168: return parameterDescriptions;
1169: }
1170:
1171: public ParameterDescription getParameterDescription(
1172: String parameterName) {
1173: // TODO: Validation: For BARE paramaterUse, only a single IN our INOUT paramater and a single output (either return or OUT or INOUT) is allowed
1174: // Per JSR-224, Sec 3.6.2.2, pg 37
1175: ParameterDescription matchingParamDesc = null;
1176: if (parameterName != null && !parameterName.equals("")) {
1177: for (ParameterDescription paramDesc : parameterDescriptions) {
1178: if (parameterName.equals(paramDesc.getParameterName())) {
1179: matchingParamDesc = paramDesc;
1180: break;
1181: }
1182: }
1183: }
1184: return matchingParamDesc;
1185: }
1186:
1187: public ParameterDescription getParameterDescription(
1188: int parameterNumber) {
1189: return parameterDescriptions[parameterNumber];
1190: }
1191:
1192: public String[] getParamNames() {
1193: // REVIEW: WSDL/Anno merge
1194: return getAnnoWebParamNames();
1195: }
1196:
1197: public String[] getAnnoWebParamNames() {
1198: if (webParamNames == null) {
1199: ArrayList<String> buildNames = new ArrayList<String>();
1200: ParameterDescription[] paramDescs = getParameterDescriptions();
1201: for (ParameterDescription currentParamDesc : paramDescs) {
1202: buildNames.add(currentParamDesc.getParameterName());
1203: }
1204: webParamNames = buildNames.toArray(new String[0]);
1205: }
1206: return webParamNames;
1207: }
1208:
1209: public String[] getAnnoWebParamTargetNamespaces() {
1210: if (webParamTargetNamespace == null) {
1211: ArrayList<String> buildTargetNS = new ArrayList<String>();
1212: ParameterDescription[] paramDescs = getParameterDescriptions();
1213: for (ParameterDescription currentParamDesc : paramDescs) {
1214: buildTargetNS
1215: .add(currentParamDesc.getTargetNamespace());
1216: }
1217: webParamTargetNamespace = buildTargetNS
1218: .toArray(new String[0]);
1219: }
1220: return webParamTargetNamespace;
1221: }
1222:
1223: public String getAnnoWebParamTargetNamespace(String name) {
1224: String returnTargetNS = null;
1225: ParameterDescription paramDesc = getParameterDescription(name);
1226: if (paramDesc != null) {
1227: returnTargetNS = paramDesc.getTargetNamespace();
1228: }
1229: return returnTargetNS;
1230: }
1231:
1232: public Mode[] getAnnoWebParamModes() {
1233: if (webParamMode == null) {
1234: ArrayList<Mode> buildModes = new ArrayList<Mode>();
1235: ParameterDescription[] paramDescs = getParameterDescriptions();
1236: for (ParameterDescription currentParamDesc : paramDescs) {
1237: // TODO: Consider new ParamDesc.Mode vs WebParam.Mode
1238: buildModes
1239: .add(((ParameterDescriptionJava) currentParamDesc)
1240: .getAnnoWebParamMode());
1241: }
1242: webParamMode = buildModes.toArray(new Mode[0]);
1243: }
1244: return webParamMode;
1245: }
1246:
1247: public boolean isAnnoWebParamHeader(String name) {
1248: ParameterDescription paramDesc = getParameterDescription(name);
1249: if (paramDesc != null) {
1250: return paramDesc.isHeader();
1251: }
1252: return false;
1253: }
1254:
1255: // ===========================================
1256: // ANNOTATION: WebResult
1257: // ===========================================
1258: public WebResult getAnnoWebResult() {
1259: if (webResultAnnotation == null) {
1260: if (!isDBC() && seiMethod != null) {
1261: webResultAnnotation = seiMethod
1262: .getAnnotation(WebResult.class);
1263: } else if (methodComposite != null) {
1264: webResultAnnotation = methodComposite
1265: .getWebResultAnnot();
1266: } else {
1267: if (log.isDebugEnabled()) {
1268: log.debug("Unable to get WebResult annotation");
1269: }
1270: }
1271: }
1272: return webResultAnnotation;
1273: }
1274:
1275: public boolean isWebResultAnnotationSpecified() {
1276: return getAnnoWebResult() != null;
1277: }
1278:
1279: public boolean isOperationReturningResult() {
1280: boolean isResult = false;
1281: if (!isAnnoOneWay()) {
1282: if (!isDBC() && seiMethod != null) {
1283: if (seiMethod.getReturnType() != Void.TYPE) {
1284: isResult = true;
1285: }
1286: } else if (methodComposite != null) {
1287: if (!DescriptionUtils.isEmpty(methodComposite
1288: .getReturnType())
1289: && !methodComposite.getReturnType().equals(
1290: "void"))
1291: isResult = true;
1292: } else {
1293: if (log.isDebugEnabled()) {
1294: log
1295: .debug("No class to determine if result is returned");
1296: }
1297: }
1298: }
1299: return isResult;
1300: }
1301:
1302: public String getResultName() {
1303: // REVIEW: WSDL/Anno merge
1304: return getAnnoWebResultName();
1305: }
1306:
1307: public String getAnnoWebResultName() {
1308: if (!isOperationReturningResult()) {
1309: return null;
1310: }
1311: if (webResultName == null) {
1312: if (getAnnoWebResult() != null
1313: && !DescriptionUtils.isEmpty(getAnnoWebResult()
1314: .name())) {
1315: webResultName = getAnnoWebResult().name();
1316: } else if (getAnnoSoapBindingStyle() == SOAPBinding.Style.DOCUMENT
1317: && getAnnoSoapBindingParameterStyle() == SOAPBinding.ParameterStyle.BARE) {
1318: // Default for operation style DOCUMENT and paramater style BARE per JSR 181 MR Sec 4.5.1, pg 23
1319: webResultName = getAnnoWebMethodOperationName()
1320: + "Response";
1321:
1322: } else {
1323: // Defeault value is "return" per JSR-181 MR Sec. 4.5.1, p. 22
1324: webResultName = "return";
1325: }
1326: }
1327: return webResultName;
1328: }
1329:
1330: public String getResultPartName() {
1331: // REVIEW: WSDL/Anno merge
1332: return getAnnoWebResultPartName();
1333: }
1334:
1335: public String getAnnoWebResultPartName() {
1336: if (!isOperationReturningResult()) {
1337: return null;
1338: }
1339: if (webResultPartName == null) {
1340: if (getAnnoWebResult() != null
1341: && !DescriptionUtils.isEmpty(getAnnoWebResult()
1342: .partName())) {
1343: webResultPartName = getAnnoWebResult().partName();
1344: } else {
1345: // Default is the WebResult.name per JSR-181 MR Sec 4.5.1, pg 23
1346: webResultPartName = getAnnoWebResultName();
1347: }
1348: }
1349: return webResultPartName;
1350: }
1351:
1352: public String getResultTargetNamespace() {
1353: // REVIEW: WSDL/Anno merge
1354: return getAnnoWebResultTargetNamespace();
1355: }
1356:
1357: public String getAnnoWebResultTargetNamespace() {
1358: if (!isOperationReturningResult()) {
1359: return null;
1360: }
1361: if (webResultTargetNamespace == null) {
1362: if (getAnnoWebResult() != null
1363: && !DescriptionUtils.isEmpty(getAnnoWebResult()
1364: .targetNamespace())) {
1365: webResultTargetNamespace = getAnnoWebResult()
1366: .targetNamespace();
1367: } else if (getAnnoSoapBindingStyle() == SOAPBinding.Style.DOCUMENT
1368: && getAnnoSoapBindingParameterStyle() == SOAPBinding.ParameterStyle.WRAPPED
1369: && !getAnnoWebResultHeader()) {
1370: // Default for operation style DOCUMENT and paramater style WRAPPED and the return value
1371: // does not map to a header per JSR-181 MR Sec 4.5.1, pg 23-24
1372: webResultTargetNamespace = WebResult_TargetNamespace_DEFAULT;
1373: } else {
1374: // Default is the namespace from the WebService per JSR-181 MR Sec 4.5.1, pg 23-24
1375: webResultTargetNamespace = ((EndpointDescriptionJava) getEndpointInterfaceDescription()
1376: .getEndpointDescription())
1377: .getAnnoWebServiceTargetNamespace();
1378: }
1379:
1380: }
1381: return webResultTargetNamespace;
1382: }
1383:
1384: public boolean isResultHeader() {
1385: // REVIEW: WSDL/Anno merge
1386: return getAnnoWebResultHeader();
1387: }
1388:
1389: public boolean getAnnoWebResultHeader() {
1390: if (!isOperationReturningResult()) {
1391: return false;
1392: }
1393: if (webResultHeader == null) {
1394: if (getAnnoWebResult() != null) {
1395: // Unlike the elements with a String value, if the annotation is present, exclude will always
1396: // return a usable value since it will default to FALSE if the element is not present.
1397: webResultHeader = new Boolean(getAnnoWebResult()
1398: .header());
1399: } else {
1400: webResultHeader = WebResult_Header_DEFAULT;
1401: }
1402: }
1403: return webResultHeader.booleanValue();
1404: }
1405:
1406: // ===========================================
1407: // ANNOTATION: SOAPBinding
1408: // ===========================================
1409: public SOAPBinding getAnnoSoapBinding() {
1410: // TODO: VALIDATION: Only style of DOCUMENT allowed on Method annotation; remember to check the Type's style setting also
1411: // JSR-181 Sec 4.7 p. 28
1412: if (soapBindingAnnotation == null) {
1413: if (!isDBC() && seiMethod != null) {
1414: soapBindingAnnotation = seiMethod
1415: .getAnnotation(SOAPBinding.class);
1416: } else if (isDBC() && methodComposite != null) {
1417: soapBindingAnnotation = methodComposite
1418: .getSoapBindingAnnot();
1419: } else {
1420: if (log.isDebugEnabled()) {
1421: log.debug("Unable to get SOAP Binding annotation");
1422: }
1423: }
1424: }
1425: return soapBindingAnnotation;
1426: }
1427:
1428: public javax.jws.soap.SOAPBinding.Style getSoapBindingStyle() {
1429: // REVIEW: WSDL/Anno merge
1430: return getAnnoSoapBindingStyle();
1431: }
1432:
1433: public javax.jws.soap.SOAPBinding.Style getAnnoSoapBindingStyle() {
1434: if (soapBindingStyle == null) {
1435: if (getAnnoSoapBinding() != null
1436: && getAnnoSoapBinding().style() != null) {
1437: soapBindingStyle = getAnnoSoapBinding().style();
1438: } else {
1439: // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value.
1440: soapBindingStyle = getEndpointInterfaceDescription()
1441: .getSoapBindingStyle();
1442: }
1443: }
1444: return soapBindingStyle;
1445: }
1446:
1447: public javax.jws.soap.SOAPBinding.Use getSoapBindingUse() {
1448: // REVIEW: WSDL/Anno merge
1449: return getAnnoSoapBindingUse();
1450: }
1451:
1452: public javax.jws.soap.SOAPBinding.Use getAnnoSoapBindingUse() {
1453: if (soapBindingUse == null) {
1454: if (getAnnoSoapBinding() != null
1455: && getAnnoSoapBinding().use() != null) {
1456: soapBindingUse = getAnnoSoapBinding().use();
1457: } else {
1458: // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value.
1459: soapBindingUse = getEndpointInterfaceDescription()
1460: .getSoapBindingUse();
1461: }
1462: }
1463: return soapBindingUse;
1464: }
1465:
1466: public javax.jws.soap.SOAPBinding.ParameterStyle getSoapBindingParameterStyle() {
1467: // REVIEW: WSDL/Anno merge
1468: return getAnnoSoapBindingParameterStyle();
1469: }
1470:
1471: public javax.jws.soap.SOAPBinding.ParameterStyle getAnnoSoapBindingParameterStyle() {
1472: if (soapBindingParameterStyle == null) {
1473: if (getAnnoSoapBinding() != null
1474: && getAnnoSoapBinding().parameterStyle() != null) {
1475: soapBindingParameterStyle = getAnnoSoapBinding()
1476: .parameterStyle();
1477: } else {
1478: // Per JSR-181 MR Sec 4.7, pg 28: if not specified, use the Type value.
1479: soapBindingParameterStyle = getEndpointInterfaceDescription()
1480: .getSoapBindingParameterStyle();
1481: }
1482: }
1483: return soapBindingParameterStyle;
1484: }
1485:
1486: // ===========================================
1487: // ANNOTATION: OneWay
1488: // ===========================================
1489: public Oneway getAnnoOneway() {
1490: //TODO: Shouldn't really do it this way...if there is not Oneway annotation,
1491: // we will always be calling the methods to try to retrieve it, since
1492: // it will always be null, should consider relying on 'isOneWay'
1493:
1494: if (onewayAnnotation == null) {
1495: if (isDBC() && methodComposite != null) {
1496: if (methodComposite.isOneWay()) {
1497: onewayAnnotation = OneWayAnnot
1498: .createOneWayAnnotImpl();
1499: }
1500: } else if (!isDBC() && seiMethod != null) {
1501: onewayAnnotation = seiMethod
1502: .getAnnotation(Oneway.class);
1503: } else {
1504: if (log.isDebugEnabled()) {
1505: log.debug("Unable to get OneWay annotation");
1506: }
1507: }
1508: }
1509: return onewayAnnotation;
1510: }
1511:
1512: public boolean isOneWay() {
1513: // REVIEW: WSDL/Anno merge
1514: return isAnnoOneWay();
1515: }
1516:
1517: public boolean isAnnoOneWay() {
1518: if (onewayIsOneway == null) {
1519: if (getAnnoOneway() != null) {
1520: // The presence of the annotation indicates the method is oneway
1521: onewayIsOneway = new Boolean(true);
1522: } else {
1523: // If the annotation is not present, the default is this is NOT a One Way method
1524: onewayIsOneway = new Boolean(false);
1525: }
1526: }
1527: return onewayIsOneway.booleanValue();
1528: }
1529:
1530: private boolean isDBC() {
1531: if (methodComposite != null)
1532: return true;
1533: else
1534: return false;
1535: }
1536:
1537: /* (non-Javadoc)
1538: * @see org.apache.axis2.jaxws.description.OperationDescription#getResultType()
1539: */
1540: public Class getResultType() {
1541: Class returnClass = null;
1542: if (!isDBC() && getSEIMethod() != null) {
1543: Method seiMethod = this .getSEIMethod();
1544: returnClass = seiMethod.getReturnType();
1545: } else if (methodComposite != null) {
1546: returnClass = methodComposite.getReturnTypeClass();
1547: } else {
1548: if (log.isDebugEnabled()) {
1549: log.debug("Unable to get result type from null class");
1550: }
1551: }
1552: return returnClass;
1553: }
1554:
1555: /* (non-Javadoc)
1556: * @see org.apache.axis2.jaxws.description.OperationDescription#getResultActualType()
1557: */
1558: public Class getResultActualType() {
1559: // TODO: Fix this! it isn't doing the right thing for DBC as noted below with FIXME comments
1560: // This is used to marshall the rsp on the service (dbc) and demarshall on the client (reflection)
1561: // But we shouldn't get an async OpDesc on the service since getDispatchableOperation(QN) removes them.
1562:
1563: Class returnType = getResultType();
1564: if (returnType == null) {
1565: return null;
1566: }
1567: if (isJAXWSAsyncClientMethod()) {
1568: //pooling implementation
1569: if (Response.class == returnType) {
1570: if (!isDBC()) {
1571: Type type = seiMethod.getGenericReturnType();
1572: ParameterizedType pType = (ParameterizedType) type;
1573: Type aType = pType.getActualTypeArguments()[0];
1574: if (aType != null
1575: && ParameterizedType.class
1576: .isInstance(aType)) {
1577: return (Class) ((ParameterizedType) aType)
1578: .getRawType();
1579: }
1580: return (Class) aType;
1581: } else {
1582: // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side
1583: // yet; the client is all Java Reflection. On the Service side, the Async methods are not used.
1584: // This needs to return T for Response<T>, or List for Response<List<T>>>
1585: return returnType;
1586: }
1587: }
1588: //Callback Implementation
1589: else {
1590: // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side
1591: // yet; the client is all Java Reflection. On the Service side, the Async methods are not used.
1592: // This needs to find and return T for AsyncHandler<T>, or List for AsyncHandler<List<T>>>
1593: Type[] type = getGenericParameterTypes();
1594: Class parameters[] = getParameterTypes();
1595: int i = 0;
1596: for (Class param : parameters) {
1597: if (AsyncHandler.class.isAssignableFrom(param)) {
1598: ParameterizedType pType = (ParameterizedType) type[i];
1599: Type aType = pType.getActualTypeArguments()[0];
1600: if (aType != null
1601: && ParameterizedType.class
1602: .isInstance(aType)) {
1603: return (Class) ((ParameterizedType) aType)
1604: .getRawType();
1605: }
1606: return (Class) aType;
1607: }
1608: i++;
1609: }
1610: }
1611: }
1612:
1613: return returnType;
1614: }
1615:
1616: private Type[] getGenericParameterTypes() {
1617: if (isDBC()) {
1618: // FIXME: This doesn't work for DBC. That's OK for now because DBC isn't used on the client side
1619: // yet; the client is all Java Reflection. On the Service side, the Async methods are not used.
1620: // And this method is only used to parse out the JAX-WS Async parameter types to find
1621: // AsyncHandler<T>. The problem with the code that was removed is that a Type can not be
1622: // instantiated, so we can't new up a Type inside the PDC.
1623: throw new UnsupportedOperationException(
1624: "OperationDescriptionImpl.getParameterActualGenericType not supported for DBC");
1625: // Type [] type = new Type[parameterDescriptions.length];
1626: // for (int i=0; i < parameterDescriptions.length; i++){
1627: // type[i] = ((ParameterDescriptionImpl) parameterDescriptions[i]).getParameterActualGenericType();
1628: // }
1629: // return type;
1630: } else {
1631: Type[] type = seiMethod.getGenericParameterTypes();
1632: return type;
1633: }
1634: }
1635:
1636: private Class[] getParameterTypes() {
1637: if (isDBC()) {
1638: Class[] parameters = new Class[parameterDescriptions.length];
1639: for (int i = 0; i < parameterDescriptions.length; i++) {
1640: parameters[i] = parameterDescriptions[i]
1641: .getParameterType();
1642: }
1643: return parameters;
1644: } else {
1645: Class[] parameters = seiMethod.getParameterTypes();
1646: return parameters;
1647: }
1648: }
1649:
1650: /*
1651: * (non-Javadoc)
1652: * @see org.apache.axis2.jaxws.description.OperationDescription#isJAXWSAsyncClientMethod()
1653: */
1654: public boolean isJAXWSAsyncClientMethod() {
1655: boolean answer = false;
1656: String methodName = null;
1657: String returnTypeName = null;
1658: if (isDBC()) {
1659: methodName = getMethodDescriptionComposite()
1660: .getMethodName();
1661: returnTypeName = getMethodDescriptionComposite()
1662: .getReturnType();
1663: } else {
1664: Method method = this .getSEIMethod();
1665: if (method != null) {
1666: methodName = method.getName();
1667: returnTypeName = method.getReturnType().getName();
1668: }
1669: }
1670: if (methodName != null && returnTypeName != null) {
1671: // REVIEW: Not sure the method MUST end with "Async"; I think it can be customized.
1672: answer = methodName.endsWith("Async")
1673: && (returnTypeName.equals(Response.class.getName()) || returnTypeName
1674: .equals(Future.class.getName()));
1675: }
1676: return answer;
1677: }
1678:
1679: /**
1680: * Return the Service Implementation method for this operation IFF it has been set by a previous
1681: * call to getMethodFromServiceImpl(Class serviceImplClass). Otherwise a null is returned.
1682: *
1683: * @return
1684: */
1685: private Method getMethodFromServiceImpl() {
1686: return serviceImplMethod;
1687:
1688: }
1689:
1690: public Method getMethodFromServiceImpl(Class serviceImpl) {
1691:
1692: // TODO: This doesn't support overloaded methods in the service impl This is
1693: // DIFFERENT than overloaded WSDL operations (which aren't supported). We
1694: // MUST support overloaded service impl methods as long as they have different
1695: // wsdl operation names. For example:
1696: // ServiceImple Class SEI Class
1697: // @WebMethod.name = Foo1
1698: // void foo() void foo()
1699: // @WebMethod.name = Foo2
1700: // void foo(int) void foo(int)
1701: // @WebMethod.name = Foo3
1702: // void foo(String) void foo(String)
1703: //
1704: // There will be two OpDescs, Foo1 and Foo2; the incoming wsdl operation will correctly identify
1705: // which OpDesc. However, to return the correct service impl method, we need to compare the
1706: // signatures, not just the method names.
1707: if (!serviceImplMethodFound) {
1708: Method[] methods = serviceImpl.getMethods();
1709: String opDescMethodName = getJavaMethodName();
1710: ParameterDescription[] paramDesc = getParameterDescriptions();
1711: // TODO: As noted above, a full signature is necessary, not just number of params
1712: int numberOfParams = 0;
1713: if (paramDesc != null) {
1714: numberOfParams = paramDesc.length;
1715: }
1716:
1717: // Loop through all the methods on the service impl and find the method that maps
1718: // to this OperationDescripton
1719: for (Method checkMethod : methods) {
1720: if (checkMethod.getName().equals(opDescMethodName)) {
1721: Class[] methodParams = checkMethod
1722: .getParameterTypes();
1723: // TODO: As noted above, a full signature is necessary, not just number of params
1724: if (methodParams.length == numberOfParams) {
1725: if (paramTypesMatch(paramDesc, methodParams)) {
1726: serviceImplMethod = checkMethod;
1727: break;
1728: }
1729: }
1730: }
1731: }
1732: serviceImplMethodFound = true;
1733: }
1734: return serviceImplMethod;
1735: }
1736:
1737: /**
1738: * This method will compare the types of the parameters in a <code>ParameterDescription</code>
1739: * vs. the type of the arguments in the parameters of a <code>Method</code>.
1740: *
1741: * @param paramDescs - <code>ParameterDescription</code>[]
1742: * @param methodParams - <code>Class</code>[]
1743: * @return - <code>boolean</code>
1744: */
1745: private boolean paramTypesMatch(ParameterDescription[] paramDescs,
1746: Class[] methodParams) {
1747: for (int i = 0; i < paramDescs.length; i++) {
1748: String mParamType = methodParams[i].getName();
1749: String pdType = getPDType(paramDescs[i]);
1750: if (mParamType == null || !mParamType.equals(pdType)) {
1751: return false;
1752: }
1753: }
1754: return true;
1755: }
1756:
1757: /**
1758: * This will get a <code>String</code> representing the parameter class of a
1759: * <code>ParameterDescription</code>.
1760: *
1761: * @param pd - <code>ParameterDescrition</code>
1762: * @return - <code>String</code>
1763: */
1764: private String getPDType(ParameterDescription pd) {
1765: String type = null;
1766: if (pd.getParameterType() != null) {
1767: type = pd.getParameterType().getName();
1768: } else if (pd.getParameterActualType() != null) {
1769: type = pd.getParameterActualType().getName();
1770: }
1771: return type;
1772: }
1773:
1774: public OperationRuntimeDescription getOperationRuntimeDesc(
1775: String name) {
1776: // TODO Add toString support
1777: return runtimeDescMap.get(name);
1778: }
1779:
1780: public void setOperationRuntimeDesc(OperationRuntimeDescription ord) {
1781: // TODO Add toString support
1782: runtimeDescMap.put(ord.getKey(), ord);
1783: }
1784:
1785: public boolean isListType() {
1786: return isListType;
1787: }
1788:
1789: /**
1790: * This method will return the namespace for the BindingInput that this operation
1791: * specifies. It will first look for a namespace on the WSDL Binding object and then
1792: * default to the web service's target namespace.
1793: */
1794: public String getBindingInputNamespace() {
1795: String tns = null;
1796: Binding binding = this .getEndpointInterfaceDescriptionImpl()
1797: .getEndpointDescriptionImpl().getWSDLBinding();
1798: if (binding != null) {
1799: if (log.isDebugEnabled()) {
1800: log.debug("Found WSDL binding");
1801: }
1802: // this call does not support overloaded WSDL operations as it
1803: // does not specify the name of the input and output messages
1804: BindingOperation bindingOp = binding.getBindingOperation(
1805: getOperationName(), null, null);
1806: if (bindingOp != null
1807: && bindingOp.getBindingInput() != null) {
1808: if (log.isDebugEnabled()) {
1809: log.debug("Found WSDL binding operation and input");
1810: }
1811: tns = getBindingNamespace(bindingOp.getBindingInput());
1812: if (tns != null && log.isDebugEnabled()) {
1813: log
1814: .debug("For operation: "
1815: + bindingOp.getName()
1816: + " returning the following namespace for input message"
1817: + " from WSDL: " + tns);
1818: }
1819: }
1820: }
1821: if (tns == null) {
1822: tns = getEndpointInterfaceDescription()
1823: .getTargetNamespace();
1824: if (log.isDebugEnabled()) {
1825: log
1826: .debug("For binding input returning @WebService.targetNamespace: "
1827: + tns);
1828: }
1829: }
1830: return tns;
1831: }
1832:
1833: /**
1834: * This method will return the namespace for the BindingOutput that this operation
1835: * specifies. It will first look for a namespace on the WSDL Binding object and then
1836: * default to the web service's target namespace.
1837: */
1838: public String getBindingOutputNamespace() {
1839: String tns = null;
1840: Binding binding = this .getEndpointInterfaceDescriptionImpl()
1841: .getEndpointDescriptionImpl().getWSDLBinding();
1842: if (binding != null) {
1843: if (log.isDebugEnabled()) {
1844: log.debug("Found WSDL binding");
1845: }
1846: // this call does not support overloaded WSDL operations as it
1847: // does not specify the name of the input and output messages
1848: BindingOperation bindingOp = binding.getBindingOperation(
1849: getOperationName(), null, null);
1850: if (bindingOp != null
1851: && bindingOp.getBindingOutput() != null) {
1852: if (log.isDebugEnabled()) {
1853: log
1854: .debug("Found WSDL binding operation and output");
1855: }
1856: tns = getBindingNamespace(bindingOp.getBindingOutput());
1857: if (tns != null && log.isDebugEnabled()) {
1858: log
1859: .debug("For operation: "
1860: + bindingOp.getName()
1861: + " returning the following namespace for output message"
1862: + " from WSDL: " + tns);
1863: }
1864: }
1865: }
1866: if (tns == null) {
1867: tns = getEndpointInterfaceDescription()
1868: .getTargetNamespace();
1869: if (log.isDebugEnabled()) {
1870: log
1871: .debug("For binding output returning @WebService.targetNamespace: "
1872: + tns);
1873: }
1874: }
1875: return tns;
1876: }
1877:
1878: /**
1879: * This method will retrieve the namespace that is specified by the BindingInput or
1880: * BindingOutput object.
1881: */
1882: private String getBindingNamespace(AttributeExtensible opInfo) {
1883: if (opInfo instanceof BindingInput) {
1884: BindingInput input = (BindingInput) opInfo;
1885: return DescriptionUtils.getNamespaceFromSOAPElement(input
1886: .getExtensibilityElements());
1887: } else if (opInfo instanceof BindingOutput) {
1888: BindingOutput output = (BindingOutput) opInfo;
1889: return DescriptionUtils.getNamespaceFromSOAPElement(output
1890: .getExtensibilityElements());
1891: }
1892: return null;
1893: }
1894:
1895: public AttachmentDescription getResultAttachmentDescription() {
1896: String partName = this .getResultPartName();
1897: if (partName != null) {
1898: if (log.isDebugEnabled()) {
1899: log
1900: .debug("Returning result AttachmentDescription for partName: "
1901: + partName);
1902: }
1903: return partAttachmentMap.get(partName);
1904: }
1905: if (log.isDebugEnabled()) {
1906: log
1907: .debug("Did not find result AttachmentDescription for partName: "
1908: + partName);
1909: }
1910: return null;
1911: }
1912:
1913: /**
1914: * This method will drive the building of AttachmentDescription objects for the
1915: * operation input/output messages in the WSDL.
1916: *
1917: */
1918: private void buildAttachmentInformation() {
1919: if (log.isDebugEnabled()) {
1920: log.debug("Start buildAttachmentInformation");
1921: }
1922: // Only building attachment info if we find a full WSDL
1923: if (this .getEndpointInterfaceDescriptionImpl()
1924: .getEndpointDescriptionImpl().isWSDLFullySpecified()) {
1925: if (log.isDebugEnabled()) {
1926: log
1927: .debug("A full WSDL is available. Query the WSDL binding for the "
1928: + "AttachmentDescription information.");
1929: }
1930: DescriptionUtils.getAttachmentFromBinding(this , this
1931: .getEndpointInterfaceDescriptionImpl()
1932: .getEndpointDescriptionImpl().getWSDLBinding());
1933: } else {
1934: if (log.isDebugEnabled()) {
1935: log
1936: .debug("The WSDL is not available. Looking for @WebService wsdlLocation.");
1937: }
1938:
1939: // Try getting a WSDL
1940: String wsdlLocation = this
1941: .getEndpointInterfaceDescriptionImpl()
1942: .getEndpointDescriptionImpl()
1943: .getAnnoWebServiceWSDLLocation();
1944:
1945: if (wsdlLocation == null || wsdlLocation.length() == 0) {
1946: if (log.isDebugEnabled()) {
1947: log
1948: .debug("@WebService wsdlLocation is not specified. "
1949: + "Processing continues without AttachmentDescription information");
1950: }
1951: } else {
1952: if (log.isDebugEnabled()) {
1953: log.debug("@WebService wsdlLocation is "
1954: + wsdlLocation);
1955: }
1956:
1957: Definition def = null;
1958: WSDL4JWrapper wsdl4j = null;
1959: try {
1960: File file = new File(wsdlLocation);
1961: URL url = file.toURL();
1962: wsdl4j = new WSDL4JWrapper(url);
1963: def = wsdl4j.getDefinition();
1964: } catch (Throwable t) {
1965: if (log.isDebugEnabled()) {
1966: log
1967: .debug("Error occurred while loading WSDL. "
1968: + "Procesing continues without AttachmentDescription "
1969: + "information. " + t);
1970: }
1971: }
1972: if (def != null) {
1973: // Set the WSDL on the server
1974: this .getEndpointInterfaceDescriptionImpl()
1975: .getEndpointDescriptionImpl()
1976: .getServiceDescriptionImpl()
1977: .setWsdlWrapper(wsdl4j);
1978: if (log.isDebugEnabled()) {
1979: log
1980: .debug("WSDL Definition is loaded. Get the WSDL Binding.");
1981: }
1982:
1983: Binding binding = this
1984: .getEndpointInterfaceDescriptionImpl()
1985: .getEndpointDescriptionImpl()
1986: .getWSDLBinding();
1987:
1988: if (binding == null) {
1989: if (log.isDebugEnabled()) {
1990: log
1991: .debug("WSDL Binding was not found for serviceName="
1992: + this
1993: .getEndpointInterfaceDescription()
1994: .getEndpointDescription()
1995: .getServiceQName()
1996: + " and portName="
1997: + this
1998: .getEndpointInterfaceDescription()
1999: .getEndpointDescription()
2000: .getPortQName());
2001: }
2002: } else {
2003: if (log.isDebugEnabled()) {
2004: log
2005: .debug("Query Binding for AttachmentDescription Information");
2006: }
2007: DescriptionUtils.getAttachmentFromBinding(this ,
2008: binding);
2009: }
2010: }
2011: }
2012:
2013: }
2014: if (log.isDebugEnabled()) {
2015: log.debug("End buildAttachmentInformation");
2016: }
2017: }
2018:
2019: /**
2020: * This will return an AttachmentDescription based on a part name.
2021: */
2022: public AttachmentDescription getPartAttachmentDescription(
2023: String partName) {
2024: return partAttachmentMap.get(partName);
2025: }
2026:
2027: public void addPartAttachmentDescription(String partName,
2028: AttachmentDescription attachmentDesc) {
2029: partAttachmentMap.put(partName, attachmentDesc);
2030: }
2031:
2032: public String toString() {
2033: final String newline = "\n";
2034: final String sameline = "; ";
2035: StringBuffer string = new StringBuffer();
2036: try {
2037: string.append(super .toString());
2038: string.append(newline);
2039: string.append("Name: " + getName());
2040: string.append(sameline);
2041: string.append("Operation Name: " + getOperationName());
2042: string.append(sameline);
2043: string.append("Action: " + getAction());
2044: //
2045: string.append(newline);
2046: string.append("Operation excluded: "
2047: + (isExcluded() == true));
2048: string.append(sameline);
2049: string.append("Is oneway: " + (isOneWay() == true));
2050: string.append(sameline);
2051: string.append("Is returning result: "
2052: + (isOperationReturningResult() == true));
2053: string.append(sameline);
2054: string.append("Is result header: "
2055: + (isResultHeader() == true));
2056: string.append(sameline);
2057: string.append("Is JAXWS Client Async method: "
2058: + (isJAXWSAsyncClientMethod() == true));
2059: //
2060: string.append(newline);
2061: string.append("SOAP Style: " + getSoapBindingStyle());
2062: string.append(sameline);
2063: string.append("SOAP Use: " + getSoapBindingUse());
2064: string.append(sameline);
2065: string.append("SOAP Paramater Style: "
2066: + getSoapBindingParameterStyle());
2067: //
2068: string.append(newline);
2069: string.append("Result name: " + getResultName());
2070: string.append(sameline);
2071: string.append("Result part name: " + getResultPartName());
2072: string.append(sameline);
2073: string.append("Result type: " + getResultType());
2074: string.append(sameline);
2075: string.append("Result actual type: "
2076: + getResultActualType());
2077: if (getResultAttachmentDescription() != null) {
2078: string.append(newline);
2079: string.append(getResultAttachmentDescription()
2080: .toString());
2081: }
2082: //
2083: string.append(newline);
2084: string.append("Request Wrapper class: "
2085: + getRequestWrapperClassName());
2086: string.append(sameline);
2087: string.append("Response Wrapper class: "
2088: + getResponseWrapperClassName());
2089: //
2090: string.append(newline);
2091: string.append("Java declaring class name: "
2092: + getJavaDeclaringClassName());
2093: string.append(newline);
2094: string.append("Java method name: " + getJavaMethodName());
2095: string.append(newline);
2096: string.append("Java paramaters: " + getJavaParameters());
2097: string.append(newline);
2098: string.append("Service Implementation method: "
2099: + getMethodFromServiceImpl());
2100: string.append(newline);
2101: string.append("Axis Operation: " + getAxisOperation());
2102:
2103: string.append(newline);
2104: ParameterDescription[] paramDescs = getParameterDescriptions();
2105: if (paramDescs != null && paramDescs.length > 0) {
2106: string.append("Number of Parameter Descriptions: "
2107: + paramDescs.length);
2108: for (ParameterDescription paramDesc : paramDescs) {
2109: string.append(newline);
2110: string.append("Parameter Description: "
2111: + paramDesc.toString());
2112: }
2113: } else {
2114: string.append("No Paramater Descriptions");
2115: }
2116:
2117: string.append(newline);
2118: FaultDescription[] faultDescs = getFaultDescriptions();
2119: if (faultDescs != null && faultDescs.length > 0) {
2120: string.append("Number of Fault Descriptions: "
2121: + faultDescs.length);
2122: for (FaultDescription faultDesc : faultDescs) {
2123: string.append(newline);
2124: string.append("Fault Description: "
2125: + faultDesc.toString());
2126: }
2127: } else {
2128: string.append("No Fault Descriptions");
2129: }
2130:
2131: if (!partAttachmentMap.isEmpty()) {
2132: string.append(newline);
2133: string.append("Number of Attachment Descriptions: "
2134: + partAttachmentMap.size());
2135: string.append(newline);
2136: Iterator<AttachmentDescription> adIter = partAttachmentMap
2137: .values().iterator();
2138: while (adIter.hasNext()) {
2139: string.append(adIter.next().toString());
2140: string.append(newline);
2141: }
2142: } else {
2143: string.append(newline);
2144: string.append("No Attachment Descriptions");
2145: string.append(newline);
2146: }
2147:
2148: string.append("RuntimeDescriptions:"
2149: + this .runtimeDescMap.size());
2150: string.append(newline);
2151: for (OperationRuntimeDescription runtimeDesc : runtimeDescMap
2152: .values()) {
2153: string.append(runtimeDesc.toString());
2154: string.append(newline);
2155: }
2156: } catch (Throwable t) {
2157: string.append(newline);
2158: string
2159: .append("Complete debug information not currently available for "
2160: + "OperationDescription");
2161: return string.toString();
2162: }
2163: return string.toString();
2164: }
2165:
2166: /**
2167: * Adds a list of SOAP header QNames that are understood by JAXWS for this operation to the
2168: * AxisOperation. This will be used by Axis2 to verify that all headers marked as
2169: * mustUnderstand have been or will be processed.
2170: *
2171: * Server side headers considered understood [JAXWS 2.0 Sec 10.2.1 page 117]
2172: * - SEI method params that are in headers
2173: * - Headers processed by application handlers (TBD)
2174: *
2175: * Client side headers considered understood: None
2176: *
2177: */
2178: private void registerMustUnderstandHeaders() {
2179:
2180: // REVIEW: If client side (return value, OUT or INOUT params) needs to be supported then
2181: // this needs to process client and server differently.
2182:
2183: AxisOperation theAxisOperation = getAxisOperation();
2184: if (theAxisOperation == null) {
2185: if (log.isDebugEnabled()) {
2186: log
2187: .debug("The axis operation is null, so header QNames could not be registered. OpDesc = "
2188: + this );
2189: }
2190: return;
2191: }
2192:
2193: // If any IN or INOUT parameters are in the header, then add their QNames to the list
2194: ParameterDescription paramDescs[] = getParameterDescriptions();
2195: ArrayList understoodQNames = new ArrayList();
2196: if (paramDescs != null && paramDescs.length > 0) {
2197: for (ParameterDescription paramDesc : paramDescs) {
2198: if (paramDesc.isHeader()
2199: && (paramDesc.getMode() == WebParam.Mode.IN || paramDesc
2200: .getMode() == WebParam.Mode.INOUT)) {
2201: QName headerQN = new QName(paramDesc
2202: .getTargetNamespace(), paramDesc
2203: .getParameterName());
2204: understoodQNames.add(headerQN);
2205: if (log.isDebugEnabled()) {
2206: log
2207: .debug("OpDesc: understoodQName added to AxisOperation (if not null) "
2208: + headerQN);
2209: }
2210: }
2211: }
2212: }
2213:
2214: if (!understoodQNames.isEmpty()) {
2215: Parameter headerQNParameter = new Parameter(
2216: OperationDescription.HEADER_PARAMETER_QNAMES,
2217: understoodQNames);
2218: try {
2219: theAxisOperation.addParameter(headerQNParameter);
2220: } catch (AxisFault e) {
2221: // TODO: RAS
2222: log.warn(
2223: "Unable to add Parameter for header QNames to AxisOperation "
2224: + theAxisOperation, e);
2225: }
2226: }
2227: }
2228:
2229: }
|