axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From whitl...@apache.org
Subject cvs commit: xml-axis-wsif/java/src/org/apache/wsif WSIFClientProxy.java
Date Tue, 09 Jul 2002 13:53:05 GMT
whitlock    2002/07/09 06:53:05

  Modified:    java/src/org/apache/wsif/base WSIFServiceImpl.java
  Added:       java/src/org/apache/wsif/base WSIFClientProxy.java
  Removed:     java/src/org/apache/wsif WSIFClientProxy.java
  Log:
  Move WSIFClientProxy from org.apache.wsif to org.apache.wsif.base
  
  Revision  Changes    Path
  1.7       +0 -1      xml-axis-wsif/java/src/org/apache/wsif/base/WSIFServiceImpl.java
  
  Index: WSIFServiceImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis-wsif/java/src/org/apache/wsif/base/WSIFServiceImpl.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- WSIFServiceImpl.java	9 Jul 2002 10:37:12 -0000	1.6
  +++ WSIFServiceImpl.java	9 Jul 2002 13:53:05 -0000	1.7
  @@ -89,7 +89,6 @@
   import javax.xml.namespace.QName;
   
   import org.apache.soap.Constants;
  -import org.apache.wsif.WSIFClientProxy;
   import org.apache.wsif.WSIFConstants;
   import org.apache.wsif.WSIFException;
   import org.apache.wsif.WSIFMessageFactory;
  
  
  
  1.1                  xml-axis-wsif/java/src/org/apache/wsif/base/WSIFClientProxy.java
  
  Index: WSIFClientProxy.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:  
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "WSIF" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, 2002, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.wsif.base;
  
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Method;
  import java.lang.reflect.Proxy;
  import java.util.Map;
  import java.util.Iterator;
  import java.util.List;
  
  import javax.wsdl.Definition;
  import javax.wsdl.Input;
  import javax.wsdl.Message;
  import javax.wsdl.Operation;
  import javax.wsdl.Output;
  import javax.wsdl.Part;
  import javax.wsdl.PortType;
  import javax.xml.namespace.QName;
  
  import org.apache.soap.Constants;
  import org.apache.wsif.WSIFException;
  import org.apache.wsif.WSIFMessage;
  import org.apache.wsif.WSIFOperation;
  import org.apache.wsif.WSIFPort;
  import org.apache.wsif.compiler.schema.tools.Schema2Java;
  import org.apache.wsif.compiler.util.TypeMapping;
  import org.apache.wsif.logging.Tr;
  import org.apache.wsif.providers.WSIFDynamicTypeMap;
  import org.apache.wsif.providers.WSIFDynamicTypeMapping;
  import org.apache.wsif.util.WSIFUtils;
  
  /**
   * WSIFClientProxy is a dynamic proxy (or stub) used by the 
   * WSIFServiceImpl when the application is using the stubs to 
   * invoke the web service. A WSIFClientProxy is created using the 
   * static newInstance method. A WSIFClientProxy dynamically implements
   * exactly one interface passed by the application. This class
   * invokes the web service using the WSIFOperation and WSIFPort 
   * interfaces and so is independent of any provider implementation.
   * Operation overloading is supported.
   * 
   * @author Owen Burroughs <owenb@apache.org>
   * @author Ant Elder <antelder@apache.org>
   * @author Jeremy Hughes <hughesj@apache.org>
   * @author Mark Whitlock <whitlock@apache.org>
   */
  public class WSIFClientProxy implements InvocationHandler {
      protected Class iface = null;
      protected Definition def = null;
      protected String serviceNS = null;
      protected String serviceName = null;
      protected String portTypeNS = null;
      protected String portTypeName = null;
      protected WSIFDynamicTypeMap typeMap = null;
      protected Map simpleTypeReg = null;
      protected PortType portType = null;
      protected WSIFPort wsifport = null;
      protected Object proxy = null;
  
      /**
       * Factory method to create a new dynamic proxy.
       * @param iface the user interface that is to be dynamically implemented
       * @param def the WSDL definition
       * @param serviceNS WSDL service namespace
       * @param serviceName WSDL service name
       * @param portTypeNS WSDL port type namespace
       * @param portTypeName WSDL port type name
       * @param typeMap table of mappings between XML and Java types
       * @return the new WSIFClientProxy
       * @exception WSIFException 
       */
      public static WSIFClientProxy newInstance(
          Class iface,
          Definition def,
          String serviceNS,
          String serviceName,
          String portTypeNS,
          String portTypeName,
          WSIFDynamicTypeMap typeMap)
          throws WSIFException {
          Tr.entry(
              null,
              iface,
              def,
              serviceNS,
              serviceName,
              portTypeNS,
              portTypeName,
              typeMap);
  
          if (!iface.isInterface())
              throw new WSIFException(
                  "Cannot get a stub for " + iface + " because it is not an interface");
  
          WSIFClientProxy clientProxy =
              new WSIFClientProxy(
                  iface,
                  def,
                  serviceNS,
                  serviceName,
                  portTypeNS,
                  portTypeName,
                  typeMap);
  
          Object proxy =
              Proxy.newProxyInstance(
                  iface.getClassLoader(),
                  new Class[] { iface },
                  clientProxy);
  
          clientProxy.setProxy(proxy);
  
          if (Tr.ON)
              Tr.exit(clientProxy.deep());
          return clientProxy;
      }
  
      /**
       * Private constructor because newInstance() should be used instead.
       */
      private WSIFClientProxy(
          Class iface,
          Definition def,
          String serviceNS,
          String serviceName,
          String portTypeNS,
          String portTypeName,
          WSIFDynamicTypeMap typeMap)
          throws WSIFException {
          Tr.entry(
              this,
              iface,
              def,
              serviceNS,
              serviceName,
              portTypeNS,
              portTypeName,
              typeMap);
          this.iface = iface;
          this.def = def;
          this.serviceNS = serviceNS;
          this.serviceName = serviceName;
          this.portTypeNS = portTypeNS;
          this.portTypeName = portTypeName;
          this.typeMap = typeMap;
          this.portType = WSIFUtils.selectPortType(def, portTypeNS, portTypeName);
  
          simpleTypeReg = WSIFUtils.getSimpleTypesMap();
  
          Tr.exit();
      }
  
      private void setProxy(Object proxy) {
          this.proxy = proxy;
      }
      
      public Object getProxy() {
          return this.proxy;
      }
  
      /**
       * Select which port to use for this proxy.
       */
      public void setPort(WSIFPort wsifport) {
          Tr.entry(this, wsifport);
          this.wsifport = wsifport;
          Tr.exit();
      }
  
      /**
       * Invoke a user method. The java proxy support calls this method.
       * 
       * The fault from the fault message is not passed back to caller 
       * (but it should be). However none of the existing providers set 
       * the fault message. I'm not sure what to do with the fault message
       * anyhow. I guess raise a WSIFException which is what the current
       * providers do with faults already.
       */
      public Object invoke(Object proxy, Method method, Object[] args)
          throws WSIFException {
          Tr.entry(this, method, args); // Tracing proxy cause a hang
  
          Operation operation = findMatchingOperation(method,args);
  
          // Now set up the input and output messages.      
          Input input = operation.getInput();
          Output output = operation.getOutput();
          String inputName = (input == null) ? null : input.getName();
          String outputName = (output == null) ? null : output.getName();
          Message inputMessage = (input == null) ? null : input.getMessage();
          Message outputMessage = (output == null) ? null : output.getMessage();
  
          WSIFOperation wsifoperation =
              wsifport.createOperation(method.getName(), inputName, outputName);
  
          // make the msg names for compiled msgs xxxAnt ask Mark why diff from inputName

          String inputMsgName = "";
          if (input != null) {
              Message m = input.getMessage();
              if (m != null) {
                  QName qn = m.getQName();
                  inputMsgName = (qn == null) ? "" : qn.getLocalPart();
              }
          }
  
          String outputMsgName = "";
          if (output != null) {
              Message m = output.getMessage();
              if (m != null) {
                  QName qn = m.getQName();
                  outputMsgName = (qn == null) ? "" : qn.getLocalPart();
              }
          }
  
          // There must be an inputMessage.
          WSIFMessage wsifInputMessage = wsifoperation.createInputMessage(inputMsgName);
  
          // There may not be an output message.
          WSIFMessage wsifOutputMessage = null;
          WSIFMessage wsifFaultMessage = null;
          if (output != null) {
              wsifOutputMessage = wsifoperation.createOutputMessage(outputMsgName);
              wsifFaultMessage = wsifoperation.createFaultMessage();
          }
  
          Iterator partIt = inputMessage.getOrderedParts(null).iterator();
          int argIndex;
          for (argIndex = 0; partIt.hasNext(); argIndex++) {
              Part part = (Part) partIt.next();
              String partName = part.getName();
              wsifInputMessage.setObjectPart(partName, args[argIndex]);
          }
  
          if (output == null)
              wsifoperation.executeInputOnlyOperation(wsifInputMessage);
          else {
              boolean success =
                  wsifoperation.executeRequestResponseOperation(
                      wsifInputMessage,
                      wsifOutputMessage,
                      wsifFaultMessage);
              if (!success) {
                  String buff = "";
                  Iterator it = wsifFaultMessage.getPartNames();
                  while (it.hasNext()) {
                      String name = (String) it.next();
                      buff += buff + name + ": " + wsifFaultMessage.getObjectPart(name) +
" ";
                  }
                  throw new WSIFException(buff);
              }
          }
  
          // Copy the output part out of the message. 
          Object result = null;
          if (outputMessage != null) {
              List outputParts = outputMessage.getOrderedParts(null);
              if (outputParts != null && outputParts.size() > 0) {
                  // The return value is always the first output part
                  Iterator outPartIt = outputParts.iterator();
                  Part returnPart = (Part) outPartIt.next();
                  result = wsifOutputMessage.getObjectPart(returnPart.getName());
  
                  // Are there any inout parts? Multiple output-only parts
                  // are not allowed in java. Skip over input-only parts in the message.
                  if (outPartIt.hasNext()) {
                      Object[] inPartArr = inputMessage.getOrderedParts(null).toArray();
                      Part nextOutPart = (Part) outPartIt.next();
  
                      for (argIndex = 0; argIndex < args.length; argIndex++) {
                          if (((Part) (inPartArr[argIndex])).getName().equals(nextOutPart.getName()))
{
                              args[argIndex] = wsifOutputMessage.getObjectPart(nextOutPart.getName());
                              if (outPartIt.hasNext())
                                  nextOutPart = (Part) outPartIt.next();
                              else
                                  break; // No more output parameters
                          }
                      } // end for
                  }
              }
          }
  
          Tr.exit(result);
          return result;
      }
  
      /**
       * Find an operation in the list that matches the method and arguments.
       * 
       * Java only allows one output-only parameter and that is the return 
       * value. Java also does not allow overloading based on the return value.
       * Consequently we only look at the input parameters when deciding 
       * which overloaded operation to pick.
       * 
       * If the user invoked an overloaded method, MyMethod(null) seems to be 
       * ambiguous. However it is not since java forces the user to cast the 
       * null to one of the types that are valid on the method. So the invoke
       * method on our client proxy gets passed args[0]==null which is not typed.
       * However method.getParameterTypes()[0] is the type that java picked to 
       * invoke. So we use getParameterTypes() to choose the operation, as well 
       * as args[i].getClass().
       * 
       * We also use args[i].getClass() to choose the operation in case
       * getParameterTypes()[i].equals(Object.class) (no match) but 
       * args[i].getClass() is the class specified in the operation.
       * 
       * The typeMap only contains complexTypes, so this class also uses the 
       * simpleTypeReg for simple types (int, string, etc).
       * 
       * We compare the class in the mapping with the one from types using
       * isAssignableFrom() not equals() because we allow the user to pass
       * a subclass.
       *
       * If there are two methods MyMethod(Address) and MyMethod(SubAddress) 
       * then MyMethod(new SubAddress()) would match both methods. So if we 
       * find an operation which exactly matches the method we return it. 
       * But if we find an operation whose types are assignable from the 
       * method's types, we carry on searching for an exact match. If we fail 
       * to find an exact match then we return the "assignable" match. There 
       * is a problem if there are multiple "assignable" matches and no exact 
       * match as would happen if MyMethod(SubSubAddress) where SubSubAddress
       * extends Address. This code does not cope with that case and it is a 
       * known restriction (bug).
       * 
       * If the WSDL is correct, we do not expect that there will be multiple 
       * exact matches, so we do not test for this.
       */
      private Operation findMatchingOperation(Method method, Object[] args) throws WSIFException
{
          // Check here that the method is in the interface iface
          Method[] allMethods = iface.getMethods();
          int i;
          for (i = 0; i < allMethods.length; i++)
              if (allMethods[i].equals(method))
                  break;
          if (i >= allMethods.length || !method.equals(allMethods[i]))
              throw new WSIFException(
                  "Method " + method.getName() + " is not in interface " + iface.getName());
  
          String methodName = method.getName();
          Class[] types = method.getParameterTypes();
          List opList = portType.getOperations();
          Iterator opIt = opList.iterator();
          Operation matchingOperation = null;
  
          // First try to find this method in the portType's list of operations.
          // Be careful of overloaded operations.
          while (opIt.hasNext()) {
              Operation operation = (Operation) opIt.next();
              // If the method name doesn't match the operation name this isn't the operation
              if (!methodName.equals(operation.getName()))
                  continue;
  
              Input input = operation.getInput();
              Message inputMessage = (input == null) ? null : input.getMessage();
              int numInputParts = inputMessage == null ? 0 : inputMessage.getParts().size();
  
              // Check for a match if neither args nor the operation has any parameters
              if (numInputParts == 0 && types.length == 0)
                  return operation;
  
              // No match if there are different numbers of parameters
              if (numInputParts != types.length)
                  continue;
  
              // Go through all the parameters making sure all their datatypes match
              Iterator partIt = inputMessage.getOrderedParts(null).iterator();
              boolean foundAllArgs = true;
              boolean exactMatchAllArgs = true;
              for (int argIndex = 0; partIt.hasNext() && foundAllArgs; argIndex++)
{
                  Part part = (Part) partIt.next();
                  QName partTypeName = part.getTypeName();
                  boolean foundThisArg = false;
                  boolean exactMatchThisArg = false;
  
                  // Look this parameter up in the typeMap.
                  for (Iterator mapIt = typeMap.iterator(); mapIt.hasNext() && !foundThisArg;)
{
                      WSIFDynamicTypeMapping mapping = (WSIFDynamicTypeMapping) mapIt.next();
                      if (mapping.getXmlType().equals(partTypeName)) {
                          if (mapping.getJavaType().isAssignableFrom(types[argIndex])    
    ||
                             (args[argIndex]!=null &&
                              mapping.getJavaType().isAssignableFrom(args[argIndex].getClass())))
{
                              foundThisArg = true;
                              if (mapping.getJavaType().equals(types[argIndex]) ||
                                 (args[argIndex]!=null &&
                                  mapping.getJavaType().equals(args[argIndex].getClass())))
                                  exactMatchThisArg = true;
                          } else
                              break;
                      }
                  }
  
                  // Look for a simple type that matches
                  TypeMapping tm = (TypeMapping) (simpleTypeReg.get(partTypeName));
                  if (!foundThisArg && tm != null) {
                      String simpleType = tm.javaType;
                      if (types[argIndex].toString().equals(simpleType)) {
                          // this works for simple types (float, int)
                          foundThisArg = true;
                          exactMatchThisArg = true;
                      } else
                          try // this works for String, Date
                              {
                              Class simpleClass =
                                  Class.forName(simpleType, true, Thread.currentThread().getContextClassLoader());
                              if (simpleClass.isAssignableFrom(types[argIndex])) {
                                  foundThisArg = true;
                                  if (simpleClass.equals(types[argIndex]))
                                      exactMatchThisArg = true;
                              }
                          } catch (ClassNotFoundException ignored) {
                          }
                  }
  
                  if (!foundThisArg)
                      foundAllArgs = false;
                  if (!exactMatchThisArg)
                      exactMatchAllArgs = false;
              }
  
              if (foundAllArgs) {
                  if (exactMatchAllArgs)
                      return operation;
  
                  // if matchingOperation!=null then write trace statement.
                  matchingOperation = operation;
              }
          } // end while
  
          if (matchingOperation != null)
              return matchingOperation;
  
          // if we get here then we haven't found a matching operation       
          String argString = new String();
          if (types != null)
              for (i = 0; i < types.length; i++) {
                  if (i != 0)
                      argString += ", ";
                  argString += types[i];
              }
  
          throw new WSIFException(
              "Method "
                  + methodName
                  + "("
                  + argString
                  + ") was not found in portType "
                  + portType.getQName());
      }
  
      public String deep() {
          String buff = "";
          try {
              buff = new String(this.toString() + "\n");
              buff += "iface: " + iface;
              buff += " def: " + Tr.brief(def);
              buff += " serviceNS: " + serviceNS;
              buff += " serviceName: " + serviceName;
              buff += " portTypeNS: " + portTypeNS;
              buff += " portTypeName: " + portTypeName;
              buff += " typeMap: " + typeMap;
              buff += "\nsimpleTypeReg: " + simpleTypeReg;
              buff += "\nportType: " + Tr.brief(portType);
              buff += " wsifport: " + wsifport;
  
              // Can't trace proxy here because it causes a hang.
              //buff += "proxy: " + proxy;
          } catch (Exception e) {
              Tr.exceptionInTrace(e);
          }
          return buff;
      }
  }
  
  
  

Mime
View raw message