Tom,
You accidentally added SOAPFaultDetailsBuilder.java to the head branch, and it contains code that is only in the interop4 branch. I'll let you decide how to fix this. B.T.W. I haven't reviewed your changes yet, but thanks for doing this work. Rich Scheuerle IBM WebSphere & Axis Web Services Development 512-838-5115 (IBM TL 678-5115) R J Scheuerle Jr/Austin/IBM@IBM To: [EMAIL PROTECTED] US cc: Subject: Re: cvs commit: xml-axis/java/src/org/apache/axis/client Service.java 10/01/2002 04:43 PM Please respond to axis-dev I am getting compile errors. Are you sure you checked in all the changes. Getting a compiler error in SOAPFaultDetailsBuilder.java line 121: can't resolve symbol Service.FaultInfo Rich Scheuerle IBM WebSphere & Axis Web Services Development 512-838-5115 (IBM TL 678-5115) [EMAIL PROTECTED] To: [EMAIL PROTECTED] 10/01/2002 03:38 cc: PM Subject: cvs commit: xml-axis/java/src/org/apache/axis/client Service.java Please respond to axis-dev 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 [EMAIL PROTECTED] * * 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 ([EMAIL PROTECTED]) * @author Tom Jordahl ([EMAIL PROTECTED]) */ 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); } }