aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package com.sun.xml.internal.ws.model; aoqi@0: aoqi@0: import com.sun.xml.internal.bind.api.TypeReference; aoqi@0: import com.sun.xml.internal.ws.api.databinding.MetadataReader; aoqi@0: import com.sun.xml.internal.ws.api.model.JavaMethod; aoqi@0: import com.sun.xml.internal.ws.api.model.MEP; aoqi@0: import com.sun.xml.internal.ws.api.model.SEIModel; aoqi@0: import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; aoqi@0: import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; aoqi@0: import com.sun.xml.internal.ws.api.model.wsdl.WSDLFault; aoqi@0: import com.sun.xml.internal.ws.api.model.soap.SOAPBinding; aoqi@0: import com.sun.xml.internal.ws.model.soap.SOAPBindingImpl; aoqi@0: import com.sun.xml.internal.ws.spi.db.TypeInfo; aoqi@0: import com.sun.xml.internal.ws.wsdl.ActionBasedOperationSignature; aoqi@0: import com.sun.istack.internal.Nullable; aoqi@0: aoqi@0: import javax.xml.namespace.QName; aoqi@0: import javax.xml.ws.Action; aoqi@0: import javax.xml.ws.WebServiceException; aoqi@0: import javax.jws.WebMethod; aoqi@0: import java.lang.reflect.Method; aoqi@0: import java.util.ArrayList; aoqi@0: import java.util.Collections; aoqi@0: import java.util.List; aoqi@0: import java.util.logging.Logger; aoqi@0: aoqi@0: /** aoqi@0: * Build this runtime model using java SEI and annotations aoqi@0: * aoqi@0: * @author Vivek Pandey aoqi@0: */ aoqi@0: public final class JavaMethodImpl implements JavaMethod { aoqi@0: aoqi@0: private String inputAction = ""; aoqi@0: private String outputAction = ""; aoqi@0: private final List exceptions = new ArrayList(); aoqi@0: private final Method method; aoqi@0: /*package*/ final List requestParams = new ArrayList(); aoqi@0: /*package*/ final List responseParams = new ArrayList(); aoqi@0: private final List unmReqParams = Collections.unmodifiableList(requestParams); aoqi@0: private final List unmResParams = Collections.unmodifiableList(responseParams); aoqi@0: private SOAPBinding binding; aoqi@0: private MEP mep; aoqi@0: private QName operationName; aoqi@0: private WSDLBoundOperation wsdlOperation; aoqi@0: /*package*/ final AbstractSEIModelImpl owner; aoqi@0: private final Method seiMethod; aoqi@0: private QName requestPayloadName; aoqi@0: private String soapAction; aoqi@0: aoqi@0: /** aoqi@0: * @param owner aoqi@0: * @param method : Implementation class method aoqi@0: * @param seiMethod : corresponding SEI Method. aoqi@0: * Is there is no SEI, it should be Implementation class method aoqi@0: */ aoqi@0: public JavaMethodImpl(AbstractSEIModelImpl owner, Method method, Method seiMethod, MetadataReader metadataReader) { aoqi@0: this.owner = owner; aoqi@0: this.method = method; aoqi@0: this.seiMethod = seiMethod; aoqi@0: setWsaActions(metadataReader); aoqi@0: } aoqi@0: aoqi@0: private void setWsaActions(MetadataReader metadataReader) { aoqi@0: Action action = (metadataReader != null)? metadataReader.getAnnotation(Action.class, seiMethod):seiMethod.getAnnotation(Action.class); aoqi@0: if(action != null) { aoqi@0: inputAction = action.input(); aoqi@0: outputAction = action.output(); aoqi@0: } aoqi@0: aoqi@0: //@Action(input) =="", get it from @WebMethod(action) aoqi@0: WebMethod webMethod = (metadataReader != null)? metadataReader.getAnnotation(WebMethod.class, seiMethod):seiMethod.getAnnotation(WebMethod.class); aoqi@0: soapAction = ""; aoqi@0: if (webMethod != null ) aoqi@0: soapAction = webMethod.action(); aoqi@0: if(!soapAction.equals("")) { aoqi@0: //non-empty soapAction aoqi@0: if(inputAction.equals("")) aoqi@0: // set input action to non-empty soapAction aoqi@0: inputAction = soapAction; aoqi@0: else if(!inputAction.equals(soapAction)){ aoqi@0: //both are explicitly set via annotations, make sure @Action == @WebMethod.action aoqi@0: //http://java.net/jira/browse/JAX_WS-1108 aoqi@0: //throw new WebServiceException("@Action and @WebMethod(action=\"\" does not match on operation "+ method.getName()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: public ActionBasedOperationSignature getOperationSignature() { aoqi@0: QName qname = getRequestPayloadName(); aoqi@0: if (qname == null) qname = new QName("", ""); aoqi@0: return new ActionBasedOperationSignature(getInputAction(), qname); aoqi@0: } aoqi@0: aoqi@0: public SEIModel getOwner() { aoqi@0: return owner; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @see JavaMethod aoqi@0: * aoqi@0: * @return Returns the method. aoqi@0: */ aoqi@0: public Method getMethod() { aoqi@0: return method; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @see JavaMethod aoqi@0: * aoqi@0: * @return Returns the SEI method where annotations are present aoqi@0: */ aoqi@0: public Method getSEIMethod() { aoqi@0: return seiMethod; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return Returns the mep. aoqi@0: */ aoqi@0: public MEP getMEP() { aoqi@0: return mep; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @param mep aoqi@0: * The mep to set. aoqi@0: */ aoqi@0: void setMEP(MEP mep) { aoqi@0: this.mep = mep; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return the Binding object aoqi@0: */ aoqi@0: public SOAPBinding getBinding() { aoqi@0: if (binding == null) aoqi@0: return new SOAPBindingImpl(); aoqi@0: return binding; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @param binding aoqi@0: */ aoqi@0: void setBinding(SOAPBinding binding) { aoqi@0: this.binding = binding; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Returns the {@link WSDLBoundOperation} Operation associated with {@link JavaMethodImpl} aoqi@0: * operation. aoqi@0: * @deprecated aoqi@0: * @return the WSDLBoundOperation for this JavaMethod aoqi@0: */ aoqi@0: public WSDLBoundOperation getOperation() { aoqi@0: // assert wsdlOperation != null; aoqi@0: return wsdlOperation; aoqi@0: } aoqi@0: aoqi@0: public void setOperationQName(QName name) { aoqi@0: this.operationName = name; aoqi@0: } aoqi@0: aoqi@0: public QName getOperationQName() { aoqi@0: return (wsdlOperation != null)? wsdlOperation.getName(): operationName; aoqi@0: } aoqi@0: aoqi@0: public String getSOAPAction() { aoqi@0: return (wsdlOperation != null)? wsdlOperation.getSOAPAction(): soapAction; aoqi@0: } aoqi@0: aoqi@0: public String getOperationName() { aoqi@0: return operationName.getLocalPart(); aoqi@0: } aoqi@0: aoqi@0: public String getRequestMessageName() { aoqi@0: return getOperationName(); aoqi@0: } aoqi@0: aoqi@0: public String getResponseMessageName() { aoqi@0: if(mep.isOneWay()) aoqi@0: return null; aoqi@0: return getOperationName()+"Response"; aoqi@0: } aoqi@0: aoqi@0: public void setRequestPayloadName(QName n) { aoqi@0: requestPayloadName = n; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return soap:Body's first child name for request message. aoqi@0: */ aoqi@0: public @Nullable QName getRequestPayloadName() { aoqi@0: return (wsdlOperation != null)? wsdlOperation.getRequestPayloadName(): requestPayloadName; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return soap:Body's first child name for response message. aoqi@0: */ aoqi@0: public @Nullable QName getResponsePayloadName() { aoqi@0: return (mep == MEP.ONE_WAY) ? null : wsdlOperation.getResponsePayloadName(); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return returns unmodifiable list of request parameters aoqi@0: */ aoqi@0: public List getRequestParameters() { aoqi@0: return unmReqParams; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return returns unmodifiable list of response parameters aoqi@0: */ aoqi@0: public List getResponseParameters() { aoqi@0: return unmResParams; aoqi@0: } aoqi@0: aoqi@0: void addParameter(ParameterImpl p) { aoqi@0: if (p.isIN() || p.isINOUT()) { aoqi@0: assert !requestParams.contains(p); aoqi@0: requestParams.add(p); aoqi@0: } aoqi@0: aoqi@0: if (p.isOUT() || p.isINOUT()) { aoqi@0: // this check is only for out parameters aoqi@0: assert !responseParams.contains(p); aoqi@0: responseParams.add(p); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void addRequestParameter(ParameterImpl p){ aoqi@0: if (p.isIN() || p.isINOUT()) { aoqi@0: requestParams.add(p); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void addResponseParameter(ParameterImpl p){ aoqi@0: if (p.isOUT() || p.isINOUT()) { aoqi@0: responseParams.add(p); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @return Returns number of java method parameters - that will be all the aoqi@0: * IN, INOUT and OUT holders aoqi@0: * aoqi@0: * @deprecated no longer use in the new architecture aoqi@0: */ aoqi@0: public int getInputParametersCount() { aoqi@0: int count = 0; aoqi@0: for (ParameterImpl param : requestParams) { aoqi@0: if (param.isWrapperStyle()) { aoqi@0: count += ((WrapperParameter) param).getWrapperChildren().size(); aoqi@0: } else { aoqi@0: count++; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: for (ParameterImpl param : responseParams) { aoqi@0: if (param.isWrapperStyle()) { aoqi@0: for (ParameterImpl wc : ((WrapperParameter) param).getWrapperChildren()) { aoqi@0: if (!wc.isResponse() && wc.isOUT()) { aoqi@0: count++; aoqi@0: } aoqi@0: } aoqi@0: } else if (!param.isResponse() && param.isOUT()) { aoqi@0: count++; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return count; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @param ce aoqi@0: */ aoqi@0: void addException(CheckedExceptionImpl ce) { aoqi@0: if (!exceptions.contains(ce)) aoqi@0: exceptions.add(ce); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @param exceptionClass aoqi@0: * @return CheckedException corresponding to the exceptionClass. Returns aoqi@0: * null if not found. aoqi@0: */ aoqi@0: public CheckedExceptionImpl getCheckedException(Class exceptionClass) { aoqi@0: for (CheckedExceptionImpl ce : exceptions) { aoqi@0: if (ce.getExceptionClass()==exceptionClass) aoqi@0: return ce; aoqi@0: } aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * @return a list of checked Exceptions thrown by this method aoqi@0: */ aoqi@0: public List getCheckedExceptions(){ aoqi@0: return Collections.unmodifiableList(exceptions); aoqi@0: } aoqi@0: aoqi@0: public String getInputAction() { aoqi@0: // return (wsdlOperation != null)? wsdlOperation.getOperation().getInput().getAction(): inputAction; aoqi@0: return inputAction; aoqi@0: } aoqi@0: aoqi@0: public String getOutputAction() { aoqi@0: // return (wsdlOperation != null)? wsdlOperation.getOperation().getOutput().getAction(): outputAction; aoqi@0: return outputAction; aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * @deprecated aoqi@0: * @param detailType aoqi@0: * @return Gets the CheckedException corresponding to detailType. Returns aoqi@0: * null if no CheckedExcpetion with the detailType found. aoqi@0: */ aoqi@0: public CheckedExceptionImpl getCheckedException(TypeReference detailType) { aoqi@0: for (CheckedExceptionImpl ce : exceptions) { aoqi@0: TypeInfo actual = ce.getDetailType(); aoqi@0: if (actual.tagName.equals(detailType.tagName) && actual.type==detailType.type) { aoqi@0: return ce; aoqi@0: } aoqi@0: } aoqi@0: return null; aoqi@0: } aoqi@0: aoqi@0: aoqi@0: aoqi@0: /** aoqi@0: * Returns if the java method is async aoqi@0: * @return if this is an Asynch aoqi@0: */ aoqi@0: public boolean isAsync(){ aoqi@0: return mep.isAsync; aoqi@0: } aoqi@0: aoqi@0: /*package*/ void freeze(WSDLPort portType) { aoqi@0: this.wsdlOperation = portType.getBinding().get(new QName(portType.getBinding().getPortType().getName().getNamespaceURI(),getOperationName())); aoqi@0: // TODO: replace this with proper error handling aoqi@0: if(wsdlOperation ==null) aoqi@0: throw new WebServiceException("Method "+seiMethod.getName()+" is exposed as WebMethod, but there is no corresponding wsdl operation with name "+operationName+" in the wsdl:portType" + portType.getBinding().getPortType().getName()); aoqi@0: aoqi@0: //so far, the inputAction, outputAction and fault actions are set from the @Action and @FaultAction aoqi@0: //set the values from WSDLModel, if such annotations are not present or defaulted aoqi@0: if(inputAction.equals("")) { aoqi@0: inputAction = wsdlOperation.getOperation().getInput().getAction(); aoqi@0: } else if(!inputAction.equals(wsdlOperation.getOperation().getInput().getAction())) aoqi@0: //TODO input action might be from @Action or WebMethod(action) aoqi@0: LOGGER.warning("Input Action on WSDL operation "+wsdlOperation.getName().getLocalPart() + " and @Action on its associated Web Method " + seiMethod.getName() +" did not match and will cause problems in dispatching the requests"); aoqi@0: aoqi@0: if (!mep.isOneWay()) { aoqi@0: if (outputAction.equals("")) aoqi@0: outputAction = wsdlOperation.getOperation().getOutput().getAction(); aoqi@0: aoqi@0: for (CheckedExceptionImpl ce : exceptions) { aoqi@0: if (ce.getFaultAction().equals("")) { aoqi@0: QName detailQName = ce.getDetailType().tagName; aoqi@0: WSDLFault wsdlfault = wsdlOperation.getOperation().getFault(detailQName); aoqi@0: if(wsdlfault == null) { aoqi@0: // mismatch between wsdl model and SEI model, log a warning and use SEI model for Action determination aoqi@0: LOGGER.warning("Mismatch between Java model and WSDL model found, For wsdl operation " + aoqi@0: wsdlOperation.getName() + ",There is no matching wsdl fault with detail QName " + aoqi@0: ce.getDetailType().tagName); aoqi@0: ce.setFaultAction(ce.getDefaultFaultAction()); aoqi@0: } else { aoqi@0: ce.setFaultAction(wsdlfault.getAction()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: final void fillTypes(List types) { aoqi@0: fillTypes(requestParams, types); aoqi@0: fillTypes(responseParams, types); aoqi@0: aoqi@0: for (CheckedExceptionImpl ce : exceptions) { aoqi@0: types.add(ce.getDetailType()); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private void fillTypes(List params, List types) { aoqi@0: for (ParameterImpl p : params) { aoqi@0: p.fillTypes(types); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static final Logger LOGGER = Logger.getLogger(com.sun.xml.internal.ws.model.JavaMethodImpl.class.getName()); aoqi@0: aoqi@0: }