You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by to...@apache.org on 2002/10/01 22:38:52 UTC

cvs commit: xml-axis/java/src/org/apache/axis/client Service.java

tomj        2002/10/01 13:38:52

  Modified:    java/src/org/apache/axis Tag: interop4 AxisFault.java
               java/src/org/apache/axis/encoding Tag: interop4
                        DeserializationContextImpl.java
                        DeserializerImpl.java
               java/src/org/apache/axis/wsdl/toJava Tag: interop4
                        JavaDefinitionWriter.java JavaFaultWriter.java
                        JavaGeneratorFactory.java JavaStubWriter.java
                        JavaTestCaseWriter.java Utils.java
               java/src/org/apache/axis/message Tag: interop4
                        MessageElement.java SOAPFault.java
                        SOAPFaultBuilder.java
               java/src/org/apache/axis/client Tag: interop4 Service.java
  Added:       java/src/org/apache/axis/message
                        SOAPFaultDetailsBuilder.java
  Log:
  Interop work for passing fault data.
  For use by Tom, Glen and Sam (maybe Dims?) for interop round 4 work.
  
  The stubs now register fault information in the Service.  The runtime uses
  this info when creating the exception for a fault, doing a lookup on each
  element in the fault details to see if its QName matches an entry in the list.
  If it does, we deserialize the element in to an object and either a) use this
  object as an argument to the Exception constructor or b) this object IS the
  Exception and we use that.
  
  On the server side, each emitted fault has a writeDetails() method which knows
  how to serialize its data.   This is called when serializing faults.
  The default AxisFault implementation of writeDetails() does nothing.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.58.2.1  +12 -7     xml-axis/java/src/org/apache/axis/AxisFault.java
  
  Index: AxisFault.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/AxisFault.java,v
  retrieving revision 1.58
  retrieving revision 1.58.2.1
  diff -u -r1.58 -r1.58.2.1
  --- AxisFault.java	17 Sep 2002 20:38:09 -0000	1.58
  +++ AxisFault.java	1 Oct 2002 20:38:51 -0000	1.58.2.1
  @@ -55,27 +55,24 @@
   
   package org.apache.axis ;
   
  +import org.apache.axis.components.logger.LogFactory;
   import org.apache.axis.encoding.SerializationContext;
   import org.apache.axis.message.SOAPEnvelope;
   import org.apache.axis.message.SOAPFault;
   import org.apache.axis.message.SOAPHeaderElement;
   import org.apache.axis.utils.JavaUtils;
   import org.apache.axis.utils.XMLUtils;
  -
  -import org.apache.axis.components.logger.LogFactory;
   import org.apache.commons.logging.Log;
  -
   import org.w3c.dom.Document;
   import org.w3c.dom.Element;
   import org.w3c.dom.Text;
   
  +import javax.xml.namespace.QName;
   import java.io.PrintStream;
   import java.lang.reflect.InvocationTargetException;
  -import java.util.Vector;
   import java.util.ArrayList;
   import java.util.Iterator;
  -
  -import javax.xml.namespace.QName;
  +import java.util.Vector;
   
   /**
    * An exception which maps cleanly to a SOAP fault.
  @@ -208,7 +205,7 @@
                                                     "exceptionName", 
                                                     target.getClass().getName());
               
  -            faultDetails.add(el);        
  +            faultDetails.add(el);
           }
           
           el =  XMLUtils.StringToElement(Constants.NS_URI_AXIS, 
  @@ -358,4 +355,12 @@
       public void clearHeaders() {
           faultHeaders = null;
       }
  +    
  +    /**
  +     *  Writes any exception data to the faultDetails
  +     */
  +    public void writeDetails(org.apache.axis.encoding.SerializationContext context) throws java.io.IOException {
  +        // no data in default Axis fault
  +    }
  +
   };
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.64.2.1  +4 -0      xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java
  
  Index: DeserializationContextImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializationContextImpl.java,v
  retrieving revision 1.64
  retrieving revision 1.64.2.1
  diff -u -r1.64 -r1.64.2.1
  --- DeserializationContextImpl.java	25 Sep 2002 22:25:24 -0000	1.64
  +++ DeserializationContextImpl.java	1 Oct 2002 20:38:51 -0000	1.64.2.1
  @@ -133,6 +133,10 @@
       private MessageElement curElement;
   
       protected int startOfMappingsPos = -1;
  +    
  +    public void deserializing(boolean isDeserializing) {
  +        doneParsing = isDeserializing;
  +    }
   
       /**
        * Construct Deserializer using MessageContext and EnvelopeBuilder handler
  
  
  
  1.30.2.1  +1 -0      xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java
  
  Index: DeserializerImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/encoding/DeserializerImpl.java,v
  retrieving revision 1.30
  retrieving revision 1.30.2.1
  diff -u -r1.30 -r1.30.2.1
  --- DeserializerImpl.java	18 Sep 2002 16:10:37 -0000	1.30
  +++ DeserializerImpl.java	1 Oct 2002 20:38:51 -0000	1.30.2.1
  @@ -489,6 +489,7 @@
                              DeserializationContext context)
           throws SAXException
       {
  +        super.endElement(namespace, localName, context);
   
           isEnded = true;
           if (!isHref) {
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.10.4.1  +1 -1      xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDefinitionWriter.java
  
  Index: JavaDefinitionWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaDefinitionWriter.java,v
  retrieving revision 1.10
  retrieving revision 1.10.4.1
  diff -u -r1.10 -r1.10.4.1
  --- JavaDefinitionWriter.java	24 Sep 2002 12:38:41 -0000	1.10
  +++ JavaDefinitionWriter.java	1 Oct 2002 20:38:51 -0000	1.10.4.1
  @@ -199,7 +199,7 @@
                           Fault f = (Fault) fi.next();
                           String name = Utils.getFullExceptionName(
                                   f,
  -                                emitter);
  +                                symbolTable);
                           // prevent duplicates
                           if (! faultList.contains(name) ) {
                               faultList.add(name);
  
  
  
  1.14.2.1  +23 -1     xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaFaultWriter.java
  
  Index: JavaFaultWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaFaultWriter.java,v
  retrieving revision 1.14
  retrieving revision 1.14.2.1
  diff -u -r1.14 -r1.14.2.1
  --- JavaFaultWriter.java	17 Sep 2002 20:33:10 -0000	1.14
  +++ JavaFaultWriter.java	1 Oct 2002 20:38:51 -0000	1.14.2.1
  @@ -77,7 +77,7 @@
        * Constructor.
        */
       protected JavaFaultWriter(Emitter emitter, QName qname, Fault fault, SymbolTable symbolTable) {
  -        super(emitter, Utils.getFullExceptionName(fault, emitter), "fault");
  +        super(emitter, Utils.getFullExceptionName(fault, symbolTable), "fault");
           this.fault = fault;
           this.symbolTable = symbolTable;
       } // ctor
  @@ -136,6 +136,28 @@
                   String variable = param.getName();
                   pw.println("        this." + variable + " = " + variable + ";");
               }
  +            pw.println("    }");
  +        }
  +        
  +        // Hack alert!
  +        // We need a QName for the exception part that we are going to
  +        // serialize, but <part name=""> isn't NOT a QName - go figure
  +        // So we will use the namespace of the Message, and the name of the part
  +        // NOTE: we do the same thing when creating the fault map in JavaStubWriter
  +        String namespace = fault.getMessage().getQName().getNamespaceURI();
  +        
  +        // method that serializes exception data (writeDetail)
  +        pw.println();
  +        pw.println("    /**");
  +        pw.println("     * Writes the exception data to the faultDetails");
  +        pw.println("     */");
  +        pw.println("    public void writeDetails(org.apache.axis.encoding.SerializationContext context) throws java.io.IOException {");
  +        for (int i = 0; i < params.size(); i++) {
  +            Parameter param = (Parameter)params.get(i);
  +            String variable = param.getName();
  +            QName qname = new QName(namespace, param.getQName().getLocalPart());
  +            pw.println("        javax.xml.namespace.QName qname = " + Utils.getNewQName(qname) + ";");
  +            pw.println("        context.serialize(qname, null, " + Utils.wrapPrimitiveType(param.getType(), variable) + ");");
               pw.println("    }");
           }
       } // writeFileBody
  
  
  
  1.26.2.1  +15 -3     xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaGeneratorFactory.java
  
  Index: JavaGeneratorFactory.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaGeneratorFactory.java,v
  retrieving revision 1.26
  retrieving revision 1.26.2.1
  diff -u -r1.26 -r1.26.2.1
  --- JavaGeneratorFactory.java	18 Sep 2002 16:10:37 -0000	1.26
  +++ JavaGeneratorFactory.java	1 Oct 2002 20:38:51 -0000	1.26.2.1
  @@ -108,6 +108,7 @@
       
       public static String COMPLEX_TYPE_FAULT = "ComplexTypeFault";
       public static String EXCEPTION_CLASS_NAME = "ExceptionClassName";
  +    public static String EXCEPTION_DATA_TYPE = "ExceptionDataType";
   
       /**
        * Default constructor.  Note that this class is unusable until setEmitter
  @@ -469,12 +470,14 @@
        * setFaultContext:
        * Helper routine for the setFaultContext method above.
        * Examines the indicated fault and sets COMPLEX_TYPE_FAULT
  -     * and EXCEPTION_CLASS_NAME as appropriate.
  +     * EXCEPTION_DATA_TYPE and EXCEPTION_CLASS_NAME as appropriate.
        * @param fault Fault to analyze
        * @param symbolTable SymbolTable
        */
       private void setFaultContext(Fault fault,
                                    SymbolTable symbolTable) {
  +        QName faultXmlType = null;
  +        
           Vector parts = new Vector();
           // Get the parts of the fault's message.
           // An IOException is thrown if the parts cannot be
  @@ -501,10 +504,16 @@
                   te = te.getRefType();
               }
   
  +            // remember the QName of the type.
  +            faultXmlType = te.getQName();
  +            
               // Determine if the te should be processed using the
               // simple type mapping or the complex type mapping
  +            // NOTE: treat array types as simple types
               if (te.getBaseType() != null ||
  -                te.isSimpleType()) {
  +                te.isSimpleType() ||
  +                  (te.getDimensions().length() > 0 && 
  +                    te.getRefType().getBaseType() != null) ) {
                   // Simple Type Exception
               } else {
                   // Complex Type Exception
  @@ -556,6 +565,9 @@
           MessageEntry me = symbolTable.getMessageEntry(
               fault.getMessage().getQName());
           if (me != null) {
  +            me.setDynamicVar(
  +                             JavaGeneratorFactory.EXCEPTION_DATA_TYPE, 
  +                             faultXmlType);
               if (exceptionClassName != null) {
                   me.setDynamicVar(
                                    JavaGeneratorFactory.COMPLEX_TYPE_FAULT, 
  @@ -923,7 +935,7 @@
               while (i.hasNext()) {
                   Fault fault = (Fault) i.next();
                   String exceptionName =
  -                  Utils.getFullExceptionName(fault, emitter);
  +                  Utils.getFullExceptionName(fault, symbolTable);
                   signature = signature + ", " + exceptionName;
               }
           }
  
  
  
  1.98.2.1  +52 -1     xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java
  
  Index: JavaStubWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaStubWriter.java,v
  retrieving revision 1.98
  retrieving revision 1.98.2.1
  diff -u -r1.98 -r1.98.2.1
  --- JavaStubWriter.java	27 Sep 2002 20:46:33 -0000	1.98
  +++ JavaStubWriter.java	1 Oct 2002 20:38:51 -0000	1.98.2.1
  @@ -54,7 +54,6 @@
    */
   package org.apache.axis.wsdl.toJava;
   
  -import org.apache.axis.utils.JavaUtils;
   import org.apache.axis.utils.Messages;
   import org.apache.axis.wsdl.symbolTable.BindingEntry;
   import org.apache.axis.wsdl.symbolTable.CollectionTE;
  @@ -67,6 +66,7 @@
   import javax.wsdl.Binding;
   import javax.wsdl.BindingOperation;
   import javax.wsdl.Fault;
  +import javax.wsdl.Message;
   import javax.wsdl.Operation;
   import javax.wsdl.OperationType;
   import javax.wsdl.Part;
  @@ -194,6 +194,9 @@
               typeMappingCount++;
           }
           
  +        // Register fault/exception information
  +        writeFaultInfo(pw, portType);
  +
           pw.println("    }");
           pw.println();
           pw.println("    private org.apache.axis.client.Call createCall() throws java.rmi.RemoteException {");
  @@ -395,6 +398,54 @@
           
       } // partTypes
   
  +    /**
  +     * This function returns the faults in an operation
  +     */
  +    private void writeFaultInfo(PrintWriter pw, PortType portType) {
  +        // Get all the faults from all the operations
  +        List operations = portType.getOperations();
  +        for (int i = 0; i < operations.size(); ++i) {
  +            Operation operation = (Operation) operations.get(i);
  +            Map faults = operation.getFaults();
  +            
  +            if (faults != null) {
  +                Iterator it = faults.values().iterator();
  +                while (it.hasNext()) {
  +                    Fault fault = (Fault) it.next();
  +
  +                    // get the name of the part - there can be only one!
  +                    Message message = fault.getMessage();
  +                    Map parts = message.getParts();
  +                    String partName = (String) parts.keySet().iterator().next();
  +
  +                    // Hack alert!
  +                    // We need a QName for the exception part that we are going to
  +                    // serialize, but <part name=""> isn't NOT a QName - go figure
  +                    // So we will use the namespace of the Message, and the name of the part
  +                    // NOTE: we do the same thing when writing the fault in JavaFaultWriter
  +                    String namespace = message.getQName().getNamespaceURI();
  +
  +                    // Now make a QName
  +                    QName qname = new QName(namespace, partName);
  +                    
  +                    // Get the Exception class name
  +                    String className = Utils.getFullExceptionName(fault, symbolTable);
  +                    
  +                    // Get the xmlType of the exception data
  +                    QName xmlType = Utils.getFaultDataType(fault, symbolTable);
  +
  +                    // output the registration API call
  +                    pw.print("      ((org.apache.axis.client.Service)service).registerFaultInfo(");
  +                     pw.print( Utils.getNewQName(qname) + ", ");
  +                     pw.print( className + ".class, ");
  +                     pw.print( Utils.getNewQName(xmlType) + ", ");
  +                     pw.print( Utils.isFaultComplex(fault, symbolTable));
  +                    pw.println(");");
  +                }
  +            }
  +        }
  +    }
  +    
       /**
        * In the stub constructor, write the serializer code for the complex types.
        */
  
  
  
  1.44.2.1  +1 -2      xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTestCaseWriter.java
  
  Index: JavaTestCaseWriter.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/JavaTestCaseWriter.java,v
  retrieving revision 1.44
  retrieving revision 1.44.2.1
  diff -u -r1.44 -r1.44.2.1
  --- JavaTestCaseWriter.java	19 Sep 2002 18:58:17 -0000	1.44
  +++ JavaTestCaseWriter.java	1 Oct 2002 20:38:51 -0000	1.44.2.1
  @@ -258,8 +258,7 @@
                       count++;
                       Fault f = (Fault) i.next();
                       pw.print("        catch (");
  -                    pw.print(Utils.getFullExceptionName(
  -                            f, emitter));
  +                    pw.print(Utils.getFullExceptionName(f, symbolTable));
                       pw.println(" e" + count + ") {");
                       pw.print("            ");
                       pw.println("throw new junit.framework.AssertionFailedError(\"" + f.getName() + " Exception caught: \" + e" + count + ");");
  
  
  
  1.58.4.1  +40 -8     xml-axis/java/src/org/apache/axis/wsdl/toJava/Utils.java
  
  Index: Utils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/wsdl/toJava/Utils.java,v
  retrieving revision 1.58
  retrieving revision 1.58.4.1
  diff -u -r1.58 -r1.58.4.1
  --- Utils.java	24 Sep 2002 17:30:29 -0000	1.58
  +++ Utils.java	1 Oct 2002 20:38:51 -0000	1.58.4.1
  @@ -223,19 +223,51 @@
        * of the exception to be generated from this fault
        * 
        * @param fault The WSDL fault object
  -     * @param emitter the Emitter being used
  +     * @param symbolTable the current symbol table
        * @return A Java class name for the fault
        */ 
  -    public static String getFullExceptionName(
  -            Fault fault, Emitter emitter) {
  -
  -        // Get the Message referenced in the message attribute of the
  -        // fault.
  +    public static String getFullExceptionName(Fault fault, 
  +                                              SymbolTable symbolTable) {
  +        // Get the Message referenced in the message attribute of the fault.
           Message faultMessage = fault.getMessage();
  -        MessageEntry me = emitter.getSymbolTable().getMessageEntry(
  -            faultMessage.getQName()); 
  +        MessageEntry me = symbolTable.getMessageEntry(faultMessage.getQName()); 
           return (String) me.getDynamicVar(JavaGeneratorFactory.EXCEPTION_CLASS_NAME);
       } // getFullExceptionName
  +
  +    /**
  +     * Given a fault, return the XML type of the exception data.
  +     * 
  +     * @param fault The WSDL fault object
  +     * @param symbolTable the current symbol table
  +     * @return A QName for the XML type of the data
  +     */ 
  +    public static QName getFaultDataType(Fault fault, 
  +                                         SymbolTable symbolTable) {
  +        // Get the Message referenced in the message attribute of the fault.
  +        Message faultMessage = fault.getMessage();
  +        MessageEntry me = symbolTable.getMessageEntry(faultMessage.getQName()); 
  +        return (QName) me.getDynamicVar(JavaGeneratorFactory.EXCEPTION_DATA_TYPE);
  +    } // getFaultDataType
  +
  +    /**
  +     * Given a fault, return TRUE if the fault is a complex type fault
  +     * 
  +     * @param fault The WSDL fault object
  +     * @param symbolTable the current symbol table
  +     * @return A Java class name for the fault
  +     */ 
  +    public static boolean isFaultComplex(Fault fault, 
  +                                         SymbolTable symbolTable) {
  +        // Get the Message referenced in the message attribute of the fault.
  +        Message faultMessage = fault.getMessage();
  +        MessageEntry me = symbolTable.getMessageEntry(faultMessage.getQName()); 
  +        Boolean ret = (Boolean) me.getDynamicVar(JavaGeneratorFactory.COMPLEX_TYPE_FAULT);
  +        if (ret != null) {
  +            return ret.booleanValue();
  +        } else {
  +            return false;
  +        }
  +    } // isFaultComplex
   
       /**
        * If the specified node represents a supported JAX-RPC enumeration,
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.129.2.1 +5 -0      xml-axis/java/src/org/apache/axis/message/MessageElement.java
  
  Index: MessageElement.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/MessageElement.java,v
  retrieving revision 1.129
  retrieving revision 1.129.2.1
  diff -u -r1.129 -r1.129.2.1
  --- MessageElement.java	25 Sep 2002 16:54:24 -0000	1.129
  +++ MessageElement.java	1 Oct 2002 20:38:52 -0000	1.129.2.1
  @@ -62,6 +62,7 @@
   import org.apache.axis.encoding.Deserializer;
   import org.apache.axis.encoding.SerializationContext;
   import org.apache.axis.encoding.SerializationContextImpl;
  +import org.apache.axis.encoding.DeserializationContextImpl;
   import org.apache.axis.utils.Mapping;
   import org.apache.axis.utils.JavaUtils;
   import org.apache.axis.utils.Messages;
  @@ -542,9 +543,13 @@
           if (dser == null)
               throw new Exception(Messages.getMessage("noDeser00", "" + type));
   
  +        boolean oldVal = context.isDoneParsing();
  +        ((DeserializationContextImpl)context).deserializing(true);
           context.pushElementHandler(new EnvelopeHandler((SOAPHandler)dser));
   
           publishToHandler((org.xml.sax.ContentHandler) context);
  +
  +        ((DeserializationContextImpl)context).deserializing(oldVal);
   
           return dser.getValue();
       }
  
  
  
  1.8.2.1   +3 -0      xml-axis/java/src/org/apache/axis/message/SOAPFault.java
  
  Index: SOAPFault.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/SOAPFault.java,v
  retrieving revision 1.8
  retrieving revision 1.8.2.1
  diff -u -r1.8 -r1.8.2.1
  --- SOAPFault.java	18 Sep 2002 16:10:28 -0000	1.8
  +++ SOAPFault.java	1 Oct 2002 20:38:52 -0000	1.8.2.1
  @@ -129,6 +129,9 @@
               Element[] faultDetails = axisFault.getFaultDetails();
               if (faultDetails != null) {
                   context.startElement(Constants.QNAME_FAULTDETAILS, null);
  +                // Allow the fault to write its data, if any
  +                axisFault.writeDetails(context);
  +                // Then output any other elements
                   for (int i = 0; i < faultDetails.length; i++) {
                       context.writeDOMElement(faultDetails[i]);
                   }
  
  
  
  1.23.8.1  +49 -12    xml-axis/java/src/org/apache/axis/message/SOAPFaultBuilder.java
  
  Index: SOAPFaultBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/SOAPFaultBuilder.java,v
  retrieving revision 1.23
  retrieving revision 1.23.8.1
  diff -u -r1.23 -r1.23.8.1
  --- SOAPFaultBuilder.java	22 Jun 2002 23:14:04 -0000	1.23
  +++ SOAPFaultBuilder.java	1 Oct 2002 20:38:52 -0000	1.23.8.1
  @@ -56,6 +56,9 @@
   
   import org.apache.axis.AxisFault;
   import org.apache.axis.Constants;
  +import org.apache.axis.MessageContext;
  +import org.apache.axis.client.Service;
  +import org.apache.axis.client.Call;
   import org.apache.axis.encoding.DeserializationContext;
   import org.apache.axis.encoding.Deserializer;
   import org.apache.axis.encoding.Callback;
  @@ -71,6 +74,7 @@
   import java.util.HashMap;
   import java.util.ArrayList;
   import java.util.Iterator;
  +import java.lang.reflect.Constructor;
   
   /** 
    * Build a Fault body element.
  @@ -86,12 +90,14 @@
       static HashMap fields = new HashMap();
       
       // Fault data
  -    protected String faultClassName = null;
       protected QName faultCode = null;
       protected String faultString = null;
       protected String faultActor = null;
       protected Element[] faultDetails;
   
  +    protected Class faultClass = null;
  +    protected Object faultData = null;
  +
       static {
           fields.put(Constants.ELEM_FAULT_CODE, Constants.XSD_STRING);
           fields.put(Constants.ELEM_FAULT_STRING, Constants.XSD_STRING);
  @@ -104,6 +110,14 @@
           this.element = element;
           this.context = context;
       }
  +    
  +    void setFaultData(Object data) {
  +        faultData = data;
  +    }
  +
  +    public void setFaultClass(Class faultClass) {
  +        this.faultClass = faultClass;
  +    }
   
       /**
        * Final call back where we can populate the exception with data.
  @@ -114,11 +128,31 @@
           super.endElement(namespace, localName, context);
           
           AxisFault f = null;
  -        if (faultClassName != null) {
  +        if (faultClass != null) {
  +            // Custom fault handling
               try {
  -                Class exClass = ClassUtils.forName(faultClassName);
  -                if (AxisFault.class.isAssignableFrom(exClass)) {
  -                    f = (AxisFault) exClass.newInstance();
  +                // If we have an element which is fault data, It can be:
  +                // 1. A simple type that needs to be passed in to the constructor
  +                // 2. A complex type that is the exception itself
  +                if (faultData != null) {
  +                    if (faultData instanceof AxisFault) {
  +                        // This is our exception class
  +                        f = (AxisFault) faultData;
  +                    } else {
  +                        // We need to create the exception, passing the data
  +                        // to the constructor
  +                        Constructor con = 
  +                                faultClass.getConstructor(
  +                                        new Class[] { faultData.getClass() });
  +                        f = (AxisFault) con.newInstance(new Object[] { faultData });
  +                    }
  +                }
  +                // If we have an AxisFault, set the fields
  +                if (AxisFault.class.isAssignableFrom(faultClass)) {
  +                    if (f == null) {
  +                        // this is to support the <exceptionName> detail
  +                        f = (AxisFault) faultClass.newInstance();
  +                    }
                       f.setFaultCode(faultCode);
                       f.setFaultString(faultString);
                       f.setFaultActor(faultActor);
  @@ -148,18 +182,24 @@
                                       DeserializationContext context)
           throws SAXException
       {
  -        Deserializer currentDeser = null;
  +        SOAPHandler retHandler = null;
           
           QName qName = (QName)fields.get(name);
           
  +        // If we found the type for this field, get the deserializer
  +        // otherwise, if this is the details element, use the special 
  +        // SOAPFaultDetailsBuilder handler to take care of custom fault data 
           if (qName != null) {
  -            currentDeser = context.getDeserializerForType(qName);
  +            Deserializer currentDeser = context.getDeserializerForType(qName);
               if (currentDeser != null) {
                   currentDeser.registerValueTarget(new CallbackTarget(this, name));
               }
  +            retHandler = (SOAPHandler) currentDeser;
  +        } else if (name.equals(Constants.ELEM_FAULT_DETAIL)) {
  +            retHandler = new SOAPFaultDetailsBuilder(this);
           }
           
  -        return (SOAPHandler)currentDeser;
  +        return retHandler;
       }
   
       public void onEndChild(String namespace, String localName,
  @@ -174,10 +214,7 @@
                       try {
                           elements[i] = ((MessageElement)children.get(i)).
                                                                       getAsDOM();
  -                        if (elements[i].getLocalName().equals("exceptionName")) {
  -                            Text text = (Text)elements[i].getFirstChild();
  -                            faultClassName = text.getData();
  -                        }
  +                        
                       } catch (Exception e) {
                           throw new SAXException(e);
                       }
  
  
  
  1.1                  xml-axis/java/src/org/apache/axis/message/SOAPFaultDetailsBuilder.java
  
  Index: SOAPFaultDetailsBuilder.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 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 "Axis" 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.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.axis.message;
  
  import org.apache.axis.AxisFault;
  import org.apache.axis.Constants;
  import org.apache.axis.MessageContext;
  import org.apache.axis.client.Service;
  import org.apache.axis.client.Call;
  import org.apache.axis.encoding.DeserializationContext;
  import org.apache.axis.encoding.Deserializer;
  import org.apache.axis.encoding.Callback;
  import org.apache.axis.encoding.CallbackTarget;
  import org.apache.axis.utils.ClassUtils;
  import org.xml.sax.Attributes;
  import org.xml.sax.SAXException;
  import org.w3c.dom.Element;
  import org.w3c.dom.Text;
  
  import javax.xml.namespace.QName;
  
  import java.util.HashMap;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.lang.reflect.Constructor;
  
  /** 
   * Handle deserializing fault details.
   * 
   * @author Glen Daniels (gdaniels@macromedia.com)
   * @author Tom Jordahl (tomj@macromedia.com)
   */
  public class SOAPFaultDetailsBuilder extends SOAPHandler implements Callback
  {
      protected SOAPFaultBuilder builder;
      
      public SOAPFaultDetailsBuilder(SOAPFaultBuilder builder) {
          this.builder = builder;
      }
  
  
      public SOAPHandler onStartChild(String namespace,
                                      String name,
                                      String prefix,
                                      Attributes attributes,
                                      DeserializationContext context)
          throws SAXException
      {
          Deserializer currentDeser = null;
          
          // Get QName of element
          QName qn = new QName(namespace, name); 
                          
          // Look for <exceptionName> element and create a class
          // with that name - this is Axis specific and is
          // replaced by the Exception map 
          if (name.equals("exceptionName")) {
              // Set up deser of exception name string
              Deserializer dser = context.getDeserializerForType(Constants.XSD_STRING);
              dser.registerValueTarget(new CallbackTarget(this, "exceptionName"));
              return (SOAPHandler)dser;
          }
                          
          // Look up this element in our faultMap
          // if we find a match, this element is the fault data
          MessageContext msgContext = context.getMessageContext();
          Service service = (Service) msgContext.getProperty(Call.WSDL_SERVICE);
          if (service != null) {
              Service.FaultInfo info = service.getFaultInfoForQName(qn);
              if (info.cls != null) {
                  // Set the class
                  builder.setFaultClass(info.cls);
                  // register callback for the data, use the xmlType from fault info
                  Deserializer dser = context.getDeserializerForType(info.xmlType);
                  dser.registerValueTarget(new CallbackTarget(this, "faultData"));
                  return (SOAPHandler)dser;
              }
          }
          
          return null;
      }
  
      /* 
       * Defined by Callback.
       * This method gets control when the callback is invoked.
       * @param is the value to set.
       * @param hint is an Object that provide additional hint information.
       */
      public void setValue(Object value, Object hint)
      {
          String name = (String)hint;
          if ("faultData".equals(hint)) {
              builder.setFaultData(value);
          } else if ("exceptionName".equals(hint)) {
              String faultClassName = (String) value;
              try {
                  Class faultClass = ClassUtils.forName(faultClassName);
                  builder.setFaultClass(faultClass);
              } catch (ClassNotFoundException e) {
                  // Just create an AxisFault, no custom exception
              }
          }
          
      }
  }
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.76.2.1  +46 -0     xml-axis/java/src/org/apache/axis/client/Service.java
  
  Index: Service.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/client/Service.java,v
  retrieving revision 1.76
  retrieving revision 1.76.2.1
  diff -u -r1.76 -r1.76.2.1
  --- Service.java	18 Sep 2002 16:10:42 -0000	1.76
  +++ Service.java	1 Oct 2002 20:38:52 -0000	1.76.2.1
  @@ -130,6 +130,12 @@
        */
       private Hashtable transportImpls = new Hashtable();
   
  +    /**
  +     * A HashMap mapping faultDetails elements (QNames) to exceptions (Class)
  +     */
  +    private HashMap faultInfoMap = new HashMap();
  +    
  +    
       Definition getWSDLDefinition() {
           return( wsdlDefinition );
       }
  @@ -767,5 +773,45 @@
        */
       Transport getTransportForURL(URL url) {
           return (Transport)transportImpls.get(url);
  +    }
  +
  +    /**
  +     * Class that describes a fault, including:
  +     * <ul>
  +     * <li>QName of the fault</li>
  +     * <li>java class of the fault</li>
  +     * <li>Qname of the XML type</li>
  +     * <li>flag indicating is this is a complex type fault</li>
  +     * </ul> 
  +     */ 
  +    public class FaultInfo {
  +        public QName qname;
  +        public Class cls;
  +        public QName xmlType;
  +        public boolean isComplex;
  +
  +        public FaultInfo(QName qname, Class cls, QName xmlType, boolean isComplex) {
  +            this.qname = qname;
  +            this.cls = cls;
  +            this.xmlType = xmlType;
  +            this.isComplex = isComplex;
  +        }
  +    }
  +    /**
  +     * Look up QName of a faultDetail element 
  +     * and return any registered Exception class
  +     */ 
  +    public FaultInfo getFaultInfoForQName(QName qname) {
  +        FaultInfo fi = (FaultInfo)faultInfoMap.get(qname);
  +        return fi;
  +    }
  +
  +    /**
  +     * register a QName of a faultDetail element 
  +     * the Exception class it coresponds to and if it is a complex type
  +     */ 
  +    public void registerFaultInfo(QName qname, Class cls, QName xmlType, boolean isComplex) {
  +        FaultInfo fi = new FaultInfo(qname, cls, xmlType, isComplex);
  +        this.faultInfoMap.put(qname, fi);
       }
   }