| /* |
| * Copyright 2002-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.axis.description; |
| |
| import org.apache.axis.components.logger.LogFactory; |
| import org.apache.axis.constants.Style; |
| import org.apache.axis.constants.Use; |
| import org.apache.commons.logging.Log; |
| |
| import javax.xml.namespace.QName; |
| import javax.wsdl.OperationType; |
| import java.io.Serializable; |
| import java.io.IOException; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.HashMap; |
| |
| |
| /** |
| * An OperationDesc is an abstract description of an operation on a service. |
| * |
| * !!! WORK IN PROGRESS |
| * |
| * @author Glen Daniels (gdaniels@apache.org) |
| */ |
| public class OperationDesc implements Serializable { |
| // Constants for "message style" operation patterns. If this OperationDesc |
| // is message style, the Java method will have one of these signatures: |
| |
| // public SOAPBodyElement [] method(SOAPBodyElement []) |
| public static final int MSG_METHOD_BODYARRAY = 1; |
| // public void method(SOAPEnvelope, SOAPEnvelope) |
| public static final int MSG_METHOD_SOAPENVELOPE = 2; |
| // public Element [] method(Element []) |
| public static final int MSG_METHOD_ELEMENTARRAY = 3; |
| // public Document method(Document) |
| public static final int MSG_METHOD_DOCUMENT = 4; |
| |
| public static final int MSG_METHOD_NONCONFORMING = -4; |
| |
| private static final Map mepStringToOperationType = new HashMap(); |
| private static final Map operationTypeToMepString = new HashMap(); |
| |
| static { |
| addMep("request-response", OperationType.REQUEST_RESPONSE); |
| addMep("oneway", OperationType.ONE_WAY); |
| addMep("solicit-response", OperationType.SOLICIT_RESPONSE); |
| addMep("notification", OperationType.NOTIFICATION); |
| } |
| |
| private static void addMep(String mepString, OperationType operationType) { |
| mepStringToOperationType.put(mepString, operationType); |
| operationTypeToMepString.put(operationType, mepString); |
| } |
| |
| protected static Log log = |
| LogFactory.getLog(OperationDesc.class.getName()); |
| |
| /** The service we're a part of */ |
| private ServiceDesc parent; |
| |
| /** Parameter list */ |
| private ArrayList parameters = new ArrayList(); |
| |
| /** The operation name (String, or QName?) */ |
| private String name; |
| |
| /** An XML QName which should dispatch to this method */ |
| private QName elementQName; |
| |
| /** The actual Java method associated with this operation, if known */ |
| private transient Method method; |
| |
| /** This operation's style/use. If null, we default to our parent's */ |
| private Style style = null; |
| private Use use = null; |
| |
| /** The number of "in" params (i.e. IN or INOUT) for this operation */ |
| private int numInParams = 0; |
| /** The number of "out" params (i.e. OUT or INOUT) for this operation */ |
| private int numOutParams = 0; |
| |
| /** A unique SOAPAction value for this operation */ |
| private String soapAction = null; |
| |
| /** Faults for this operation */ |
| private ArrayList faults = null; |
| |
| private ParameterDesc returnDesc = new ParameterDesc(); |
| |
| /** If we're a message-style operation, what's our signature? */ |
| private int messageOperationStyle = -1; |
| |
| /** The documentation for the operation */ |
| private String documentation = null; |
| |
| /** The MEP for this Operation - uses the WSDL4J OperationType for now |
| * but we might want to have our own extensible enum for WSDL 2.0 |
| */ |
| private OperationType mep = OperationType.REQUEST_RESPONSE; |
| |
| /** |
| * Default constructor. |
| */ |
| public OperationDesc() { |
| returnDesc.setMode(ParameterDesc.OUT); |
| returnDesc.setIsReturn(true); |
| } |
| |
| /** |
| * "Complete" constructor |
| */ |
| public OperationDesc(String name, ParameterDesc [] parameters, QName returnQName) { |
| this.name = name; |
| returnDesc.setQName(returnQName); |
| returnDesc.setMode(ParameterDesc.OUT); |
| returnDesc.setIsReturn(true); |
| for (int i = 0; i < parameters.length; i++) { |
| addParameter(parameters[i]); |
| } |
| } |
| |
| /** |
| * Return the operation's name |
| */ |
| public String getName() { |
| return name; |
| } |
| |
| /** |
| * Set the operation's name |
| */ |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| /** |
| * get the documentation for the operation |
| */ |
| public String getDocumentation() { |
| return documentation; |
| } |
| |
| /** |
| * set the documentation for the operation |
| */ |
| public void setDocumentation(String documentation) { |
| this.documentation = documentation; |
| } |
| |
| public QName getReturnQName() { |
| return returnDesc.getQName(); |
| } |
| |
| public void setReturnQName(QName returnQName) { |
| returnDesc.setQName(returnQName); |
| } |
| |
| public QName getReturnType() { |
| return returnDesc.getTypeQName(); |
| } |
| |
| public void setReturnType(QName returnType) { |
| log.debug("@" + Integer.toHexString(hashCode()) + "setReturnType(" + returnType +")"); |
| returnDesc.setTypeQName(returnType); |
| } |
| |
| public Class getReturnClass() { |
| return returnDesc.getJavaType(); |
| } |
| |
| public void setReturnClass(Class returnClass) { |
| returnDesc.setJavaType(returnClass); |
| } |
| |
| public QName getElementQName() { |
| return elementQName; |
| } |
| |
| public void setElementQName(QName elementQName) { |
| this.elementQName = elementQName; |
| } |
| |
| public ServiceDesc getParent() { |
| return parent; |
| } |
| |
| public void setParent(ServiceDesc parent) { |
| this.parent = parent; |
| } |
| |
| public String getSoapAction() { |
| return soapAction; |
| } |
| |
| public void setSoapAction(String soapAction) { |
| this.soapAction = soapAction; |
| } |
| |
| public void setStyle(Style style) |
| { |
| this.style = style; |
| } |
| |
| /** |
| * Return the style of the operation, defaulting to the parent |
| * ServiceDesc's style if we don't have one explicitly set. |
| */ |
| public Style getStyle() |
| { |
| if (style == null) { |
| if (parent != null) { |
| return parent.getStyle(); |
| } |
| return Style.DEFAULT; // Default |
| } |
| |
| return style; |
| } |
| |
| public void setUse(Use use) |
| { |
| this.use = use; |
| } |
| |
| /** |
| * Return the use of the operation, defaulting to the parent |
| * ServiceDesc's use if we don't have one explicitly set. |
| */ |
| public Use getUse() |
| { |
| if (use == null) { |
| if (parent != null) { |
| return parent.getUse(); |
| } |
| return Use.DEFAULT; // Default |
| } |
| |
| return use; |
| } |
| |
| public void addParameter(ParameterDesc param) |
| { |
| // Should we enforce adding INs then INOUTs then OUTs? |
| |
| param.setOrder(getNumParams()); |
| parameters.add(param); |
| if ((param.getMode() == ParameterDesc.IN) || |
| (param.getMode() == ParameterDesc.INOUT)) { |
| numInParams++; |
| } |
| if ((param.getMode() == ParameterDesc.OUT) || |
| (param.getMode() == ParameterDesc.INOUT)) { |
| numOutParams++; |
| } |
| log.debug("@" + Integer.toHexString(hashCode()) + " added parameter >" + param + "@" + Integer.toHexString(param.hashCode()) + "<total parameters:" +getNumParams()); |
| } |
| |
| public void addParameter(QName paramName, |
| QName xmlType, |
| Class javaType, |
| byte parameterMode, |
| boolean inHeader, |
| boolean outHeader) { |
| ParameterDesc param = |
| new ParameterDesc(paramName, parameterMode, xmlType, |
| javaType, inHeader, outHeader); |
| addParameter(param); |
| } |
| |
| public ParameterDesc getParameter(int i) |
| { |
| if (parameters.size() <= i) |
| return null; |
| |
| return (ParameterDesc)parameters.get(i); |
| } |
| |
| public ArrayList getParameters() { |
| return parameters; |
| } |
| |
| /** |
| * Set the parameters wholesale. |
| * |
| * @param newParameters an ArrayList of ParameterDescs |
| */ |
| public void setParameters(ArrayList newParameters) { |
| parameters = new ArrayList(); //Keep numInParams correct. |
| numInParams = 0; |
| numOutParams = 0; |
| |
| for( java.util.ListIterator li= newParameters.listIterator(); |
| li.hasNext(); ){ |
| addParameter((ParameterDesc) li.next()); |
| } |
| } |
| |
| public int getNumInParams() { |
| return numInParams; |
| } |
| |
| public int getNumOutParams() { |
| return numOutParams; |
| } |
| |
| public int getNumParams() { |
| return parameters.size(); |
| } |
| |
| public Method getMethod() { |
| return method; |
| } |
| |
| public void setMethod(Method method) { |
| this.method = method; |
| } |
| |
| /** |
| * Is the return value in the header of the response message? |
| */ |
| public boolean isReturnHeader() { |
| return returnDesc.isOutHeader(); |
| } |
| |
| /** |
| * Set whether the return value is in the response message. |
| */ |
| public void setReturnHeader(boolean value) { |
| returnDesc.setOutHeader(value); |
| } |
| |
| public ParameterDesc getParamByQName(QName qname) |
| { |
| for (Iterator i = parameters.iterator(); i.hasNext();) { |
| ParameterDesc param = (ParameterDesc) i.next(); |
| if (param.getQName().equals(qname)) |
| return param; |
| } |
| |
| return null; |
| } |
| |
| public ParameterDesc getInputParamByQName(QName qname) |
| { |
| ParameterDesc param = null; |
| |
| param = getParamByQName(qname); |
| |
| if ((param == null) || (param.getMode() == ParameterDesc.OUT)) { |
| param = null; |
| } |
| |
| return param; |
| } |
| |
| public ParameterDesc getOutputParamByQName(QName qname) |
| { |
| ParameterDesc param = null; |
| |
| for (Iterator i = parameters.iterator(); i.hasNext();) { |
| ParameterDesc pnext = (ParameterDesc)i.next(); |
| if (pnext.getQName().equals(qname) && |
| pnext.getMode() != ParameterDesc.IN) { |
| param = pnext; |
| break; |
| } |
| } |
| |
| if (param == null) { |
| if (null == returnDesc.getQName() ){ |
| param= new ParameterDesc( returnDesc); //Create copy |
| param.setQName(qname); |
| } |
| else if ( qname.equals(returnDesc.getQName())) { |
| param = returnDesc; |
| } |
| } |
| |
| return param; |
| } |
| |
| /** |
| * Return a list of ALL "in" params (including INOUTs) |
| * |
| * Note: if we were sure the order went IN->INOUT->OUT, we could optimize |
| * this. |
| * |
| * @return |
| */ |
| public ArrayList getAllInParams() { |
| ArrayList result = new ArrayList(); |
| for (Iterator i = parameters.iterator(); i.hasNext();) { |
| ParameterDesc desc = (ParameterDesc) i.next(); |
| if (desc.getMode() != ParameterDesc.OUT) { |
| result.add(desc); |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Return a list of ALL "out" params (including INOUTs) |
| * |
| * Note: if we were sure the order went IN->INOUT->OUT, we could optimize |
| * this. |
| * |
| * @return |
| */ |
| public ArrayList getAllOutParams() { |
| ArrayList result = new ArrayList(); |
| for (Iterator i = parameters.iterator(); i.hasNext();) { |
| ParameterDesc desc = (ParameterDesc) i.next(); |
| if (desc.getMode() != ParameterDesc.IN) { |
| result.add(desc); |
| } |
| } |
| return result; |
| } |
| /** |
| * Returns an ordered list of out params (NOT inouts) |
| */ |
| public ArrayList getOutParams() { |
| ArrayList result = new ArrayList(); |
| for (Iterator i = parameters.iterator(); i.hasNext();) { |
| ParameterDesc desc = (ParameterDesc) i.next(); |
| if (desc.getMode() == ParameterDesc.OUT) { |
| result.add(desc); |
| } |
| } |
| return result; |
| } |
| |
| public void addFault(FaultDesc fault) |
| { |
| if (faults == null) |
| faults = new ArrayList(); |
| faults.add(fault); |
| } |
| |
| public ArrayList getFaults() |
| { |
| return faults; |
| } |
| |
| /** |
| * Returns the FaultDesc for the fault class given. |
| * Returns null if not found. |
| */ |
| public FaultDesc getFaultByClass(Class cls) { |
| if (faults == null || cls == null) { |
| return null; |
| } |
| |
| while (cls != null) { |
| // Check each class in the inheritance hierarchy, stopping at |
| // java.* or javax.* classes. |
| |
| for (Iterator iterator = faults.iterator(); iterator.hasNext();) { |
| FaultDesc desc = (FaultDesc) iterator.next(); |
| if (cls.getName().equals(desc.getClassName())) { |
| return desc; |
| } |
| } |
| |
| cls = cls.getSuperclass(); |
| if (cls != null && (cls.getName().startsWith("java.") || |
| cls.getName().startsWith("javax."))) { |
| cls = null; |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the FaultDesc for the fault class given. |
| * Returns null if not found. |
| */ |
| public FaultDesc getFaultByClass(Class cls, boolean checkParents) { |
| if (checkParents) { |
| return getFaultByClass(cls); |
| } |
| |
| if (faults == null || cls == null) { |
| return null; |
| } |
| |
| for (Iterator iterator = faults.iterator(); iterator.hasNext();) { |
| FaultDesc desc = (FaultDesc) iterator.next(); |
| if (cls.getName().equals(desc.getClassName())) { |
| return desc; |
| } |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Returns the FaultDesc for a QName (which is typically found |
| * in the details element of a SOAP fault). |
| * Returns null if not found. |
| */ |
| public FaultDesc getFaultByQName(QName qname) { |
| if (faults != null) { |
| for (Iterator iterator = faults.iterator(); iterator.hasNext();) { |
| FaultDesc desc = (FaultDesc) iterator.next(); |
| if (qname.equals(desc.getQName())) { |
| return desc; |
| } |
| } |
| } |
| return null; |
| } |
| /** |
| * Returns the FaultDesc for an XMLType. |
| * Returns null if not found. |
| */ |
| public FaultDesc getFaultByXmlType(QName xmlType) { |
| if (faults != null) { |
| for (Iterator iterator = faults.iterator(); iterator.hasNext();) { |
| FaultDesc desc = (FaultDesc) iterator.next(); |
| if (xmlType.equals(desc.getXmlType())) { |
| return desc; |
| } |
| } |
| } |
| return null; |
| } |
| public ParameterDesc getReturnParamDesc() { |
| return returnDesc; |
| } |
| |
| public String toString() { |
| return toString(""); |
| } |
| public String toString(String indent) { |
| String text =""; |
| text+=indent+"name: " + getName() + "\n"; |
| text+=indent+"returnQName: " + getReturnQName() + "\n"; |
| text+=indent+"returnType: " + getReturnType() + "\n"; |
| text+=indent+"returnClass: " + getReturnClass() + "\n"; |
| text+=indent+"elementQName:" + getElementQName() + "\n"; |
| text+=indent+"soapAction: " + getSoapAction() + "\n"; |
| text+=indent+"style: " + getStyle().getName() + "\n"; |
| text+=indent+"use: " + getUse().getName() + "\n"; |
| text+=indent+"numInParams: " + getNumInParams() + "\n"; |
| text+=indent+"method:" + getMethod() + "\n"; |
| for (int i=0; i<parameters.size(); i++) { |
| text+=indent+" ParameterDesc[" + i + "]:\n"; |
| text+=indent+ ((ParameterDesc)parameters.get(i)).toString(" ") + "\n"; |
| } |
| if (faults != null) { |
| for (int i=0; i<faults.size(); i++) { |
| text+=indent+" FaultDesc[" + i + "]:\n"; |
| text+=indent+ ((FaultDesc)faults.get(i)).toString(" ") + "\n"; |
| } |
| } |
| return text; |
| } |
| |
| public int getMessageOperationStyle() { |
| return messageOperationStyle; |
| } |
| |
| public void setMessageOperationStyle(int messageOperationStyle) { |
| this.messageOperationStyle = messageOperationStyle; |
| } |
| |
| public OperationType getMep() { |
| return mep; |
| } |
| |
| public void setMep(OperationType mep) { |
| this.mep = mep; |
| } |
| |
| /** |
| * Get the MEP as a string. |
| * |
| * @return the string representation of the MEP |
| */ |
| public String getMepString() { |
| return (String)operationTypeToMepString.get(mep); |
| } |
| |
| /** |
| * Set the MEP using a string like "request-response" |
| * @param mepString |
| */ |
| public void setMep(String mepString) { |
| OperationType newMep = (OperationType)mepStringToOperationType.get(mepString); |
| if (newMep != null) { |
| mep = newMep; |
| } |
| } |
| |
| private void writeObject(java.io.ObjectOutputStream out) throws IOException { |
| out.defaultWriteObject(); |
| if (method != null){ |
| out.writeObject(method.getDeclaringClass()); |
| out.writeObject(method.getName()); |
| out.writeObject(method.getParameterTypes()); |
| } else { |
| out.writeObject(null); |
| } |
| } |
| |
| private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException{ |
| in.defaultReadObject(); |
| Class clazz = (Class) in.readObject(); |
| if (clazz != null){ |
| String methodName = (String) in.readObject(); |
| Class[] parameterTypes = (Class[]) in.readObject(); |
| try { |
| method = clazz.getMethod(methodName, parameterTypes); |
| } catch (NoSuchMethodException e) { |
| throw new IOException("Unable to deserialize the operation's method: "+ methodName); |
| } |
| } |
| } |
| } |
| |