package com.sun.xml.internal.ws.model;
import com.sun.xml.internal.bind.api.TypeReference;
import com.sun.xml.internal.ws.api.databinding.MetadataReader;
import com.sun.xml.internal.ws.api.model.JavaMethod;
import com.sun.xml.internal.ws.api.model.MEP;
import com.sun.xml.internal.ws.api.model.SEIModel;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
import com.sun.xml.internal.ws.api.model.wsdl.WSDLFault;
import com.sun.xml.internal.ws.api.model.soap.SOAPBinding;
import com.sun.xml.internal.ws.model.soap.SOAPBindingImpl;
import com.sun.xml.internal.ws.spi.db.TypeInfo;
import com.sun.xml.internal.ws.wsdl.ActionBasedOperationSignature;
import com.sun.istack.internal.Nullable;
import javax.xml.namespace.QName;
import javax.xml.ws.Action;
import javax.xml.ws.WebServiceException;
import javax.jws.WebMethod;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
public final class JavaMethodImpl implements JavaMethod {
private String inputAction = "";
private String outputAction = "";
private final List<CheckedExceptionImpl> exceptions = new ArrayList<CheckedExceptionImpl>();
private final Method method;
final List<ParameterImpl> requestParams = new ArrayList<ParameterImpl>();
final List<ParameterImpl> responseParams = new ArrayList<ParameterImpl>();
private final List<ParameterImpl> unmReqParams = Collections.unmodifiableList(requestParams);
private final List<ParameterImpl> unmResParams = Collections.unmodifiableList(responseParams);
private SOAPBinding binding;
private MEP mep;
private QName operationName;
private WSDLBoundOperation wsdlOperation;
final AbstractSEIModelImpl owner;
private final Method seiMethod;
private QName requestPayloadName;
private String soapAction;
public JavaMethodImpl(AbstractSEIModelImpl owner, Method method, Method seiMethod, MetadataReader metadataReader) {
this.owner = owner;
this.method = method;
this.seiMethod = seiMethod;
setWsaActions(metadataReader);
}
private void setWsaActions(MetadataReader metadataReader) {
Action action = (metadataReader != null)? metadataReader.getAnnotation(Action.class, seiMethod):seiMethod.getAnnotation(Action.class);
if(action != null) {
inputAction = action.input();
outputAction = action.output();
}
WebMethod webMethod = (metadataReader != null)? metadataReader.getAnnotation(WebMethod.class, seiMethod):seiMethod.getAnnotation(WebMethod.class);
soapAction = "";
if (webMethod != null )
soapAction = webMethod.action();
if(!soapAction.equals("")) {
if(inputAction.equals(""))
inputAction = soapAction;
else if(!inputAction.equals(soapAction)){
}
}
}
public ActionBasedOperationSignature getOperationSignature() {
QName qname = getRequestPayloadName();
if (qname == null) qname = new QName("", "");
return new ActionBasedOperationSignature(getInputAction(), qname);
}
public SEIModel getOwner() {
return owner;
}
public Method getMethod() {
return method;
}
public Method getSEIMethod() {
return seiMethod;
}
public MEP getMEP() {
return mep;
}
void setMEP(MEP mep) {
this.mep = mep;
}
public SOAPBinding getBinding() {
if (binding == null)
return new SOAPBindingImpl();
return binding;
}
void setBinding(SOAPBinding binding) {
this.binding = binding;
}
public WSDLBoundOperation getOperation() {
return wsdlOperation;
}
public void setOperationQName(QName name) {
this.operationName = name;
}
public QName getOperationQName() {
return (wsdlOperation != null)? wsdlOperation.getName(): operationName;
}
public String getSOAPAction() {
return (wsdlOperation != null)? wsdlOperation.getSOAPAction(): soapAction;
}
public String getOperationName() {
return operationName.getLocalPart();
}
public String getRequestMessageName() {
return getOperationName();
}
public String getResponseMessageName() {
if(mep.isOneWay())
return null;
return getOperationName()+"Response";
}
public void setRequestPayloadName(QName n) {
requestPayloadName = n;
}
public @Nullable QName getRequestPayloadName() {
return (wsdlOperation != null)? wsdlOperation.getRequestPayloadName(): requestPayloadName;
}
public @Nullable QName getResponsePayloadName() {
return (mep == MEP.ONE_WAY) ? null : wsdlOperation.getResponsePayloadName();
}
public List<ParameterImpl> getRequestParameters() {
return unmReqParams;
}
public List<ParameterImpl> getResponseParameters() {
return unmResParams;
}
void addParameter(ParameterImpl p) {
if (p.isIN() || p.isINOUT()) {
assert !requestParams.contains(p);
requestParams.add(p);
}
if (p.isOUT() || p.isINOUT()) {
assert !responseParams.contains(p);
responseParams.add(p);
}
}
void addRequestParameter(ParameterImpl p){
if (p.isIN() || p.isINOUT()) {
requestParams.add(p);
}
}
void addResponseParameter(ParameterImpl p){
if (p.isOUT() || p.isINOUT()) {
responseParams.add(p);
}
}
public int getInputParametersCount() {
int count = 0;
for (ParameterImpl param : requestParams) {
if (param.isWrapperStyle()) {
count += ((WrapperParameter) param).getWrapperChildren().size();
} else {
count++;
}
}
for (ParameterImpl param : responseParams) {
if (param.isWrapperStyle()) {
for (ParameterImpl wc : ((WrapperParameter) param).getWrapperChildren()) {
if (!wc.isResponse() && wc.isOUT()) {
count++;
}
}
} else if (!param.isResponse() && param.isOUT()) {
count++;
}
}
return count;
}
void addException(CheckedExceptionImpl ce) {
if (!exceptions.contains(ce))
exceptions.add(ce);
}
public CheckedExceptionImpl getCheckedException(Class exceptionClass) {
for (CheckedExceptionImpl ce : exceptions) {
if (ce.getExceptionClass()==exceptionClass)
return ce;
}
return null;
}
public List<CheckedExceptionImpl> getCheckedExceptions(){
return Collections.unmodifiableList(exceptions);
}
public String getInputAction() {
return inputAction;
}
public String getOutputAction() {
return outputAction;
}
public CheckedExceptionImpl getCheckedException(TypeReference detailType) {
for (CheckedExceptionImpl ce : exceptions) {
TypeInfo actual = ce.getDetailType();
if (actual.tagName.equals(detailType.tagName) && actual.type==detailType.type) {
return ce;
}
}
return null;
}
public boolean isAsync(){
return mep.isAsync;
}
void freeze(WSDLPort portType) {
this.wsdlOperation = portType.getBinding().get(new QName(portType.getBinding().getPortType().getName().getNamespaceURI(),getOperationName()));
if(wsdlOperation ==null)
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());
if(inputAction.equals("")) {
inputAction = wsdlOperation.getOperation().getInput().getAction();
} else if(!inputAction.equals(wsdlOperation.getOperation().getInput().getAction()))
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");
if (!mep.isOneWay()) {
if (outputAction.equals(""))
outputAction = wsdlOperation.getOperation().getOutput().getAction();
for (CheckedExceptionImpl ce : exceptions) {
if (ce.getFaultAction().equals("")) {
QName detailQName = ce.getDetailType().tagName;
WSDLFault wsdlfault = wsdlOperation.getOperation().getFault(detailQName);
if(wsdlfault == null) {
LOGGER.warning("Mismatch between Java model and WSDL model found, For wsdl operation " +
wsdlOperation.getName() + ",There is no matching wsdl fault with detail QName " +
ce.getDetailType().tagName);
ce.setFaultAction(ce.getDefaultFaultAction());
} else {
ce.setFaultAction(wsdlfault.getAction());
}
}
}
}
}
final void fillTypes(List<TypeInfo> types) {
fillTypes(requestParams, types);
fillTypes(responseParams, types);
for (CheckedExceptionImpl ce : exceptions) {
types.add(ce.getDetailType());
}
}
private void fillTypes(List<ParameterImpl> params, List<TypeInfo> types) {
for (ParameterImpl p : params) {
p.fillTypes(types);
}
}
private static final Logger LOGGER = Logger.getLogger(com.sun.xml.internal.ws.model.JavaMethodImpl.class.getName());
}