gdaniels    02/02/28 05:37:48

  Modified:    java/src/org/apache/axis/deployment/wsdd WSDDService.java
               java/src/org/apache/axis/handlers/soap SOAPService.java
               java/src/org/apache/axis/message BodyBuilder.java
                        RPCElement.java
               java/src/org/apache/axis/utils XMLUtils.java
  Log:
  Add support for arbitrary QName -> method mapping for doc/lit services.
  
  This allows you to configure a service (in WSDD) like this:
  
  <service name="foo" provider="java:RPC" style="document">
    <elementMapping element="foo:bar" xmlns:foo="foo" method="test"/>
    ...etc
  </service>
  
  This will automatically call the method "test" on the target class with a
  deserialized version of the <foo:bar> element as the (only, for now)
  argument.
  
  Change SOAPService to record these mappings, and BodyBuilder/
  RPCElement to use them to do the right thing.
  
  Revision  Changes    Path
  1.42      +47 -3     
xml-axis/java/src/org/apache/axis/deployment/wsdd/WSDDService.java
  
  Index: WSDDService.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/deployment/wsdd/WSDDService.java,v
  retrieving revision 1.41
  retrieving revision 1.42
  diff -u -r1.41 -r1.42
  --- WSDDService.java  27 Feb 2002 23:46:32 -0000      1.41
  +++ WSDDService.java  28 Feb 2002 13:37:47 -0000      1.42
  @@ -71,6 +71,9 @@
   
   import javax.xml.rpc.namespace.QName;
   import java.util.Vector;
  +import java.util.HashMap;
  +import java.util.Set;
  +import java.util.Iterator;
   import java.io.IOException;
   import java.beans.IntrospectionException;
   
  @@ -81,6 +84,7 @@
       extends WSDDTargetedChain
       implements WSDDTypeMappingContainer
   {
  +    public static final QName elMapQName = new QName("", "elementMapping");
       public TypeMappingRegistry tmr = null;
       
       private Vector faultFlows = new Vector();
  @@ -88,7 +92,10 @@
       
       /** Which namespaces should auto-dispatch to this service? */
       private Vector namespaces = new Vector();
  -    
  +
  +    /** List of QName -> method mappings for doc/lit dispatching */
  +    private HashMap qName2MethodMap = null;
  +
       private String descriptionURL;
       
       /** Style - document or RPC (the default) */
  @@ -145,8 +152,23 @@
               providerQName = XMLUtils.getQNameFromString(typeStr, e);
           
           String modeStr = e.getAttribute("style");
  -        if (modeStr != null && modeStr.equals("document"))
  +        if (modeStr != null && modeStr.equals("document")) {
               style = SOAPService.STYLE_DOCUMENT;
  +
  +            Element [] mappingElements = getChildElements(e, "elementMapping");
  +            if (mappingElements.length > 0 && qName2MethodMap == null) {
  +                qName2MethodMap = new HashMap();
  +            }
  +            for (int i = 0; i < mappingElements.length; i++) {
  +                // Register a mapping from an Element QName to a particular
  +                // method so we can dispatch for doc/lit services.
  +                Element el = mappingElements[i];
  +                String elString = el.getAttribute("element");
  +                QName elQName = XMLUtils.getQNameFromString(elString, el);
  +                String methodName = el.getAttribute("method");
  +                qName2MethodMap.put(elQName, methodName);
  +            }
  +        }
       }
   
       /**
  @@ -315,7 +337,9 @@
                                     faultHandler);
               }
           }
  -        
  +
  +        service.setElementMap(qName2MethodMap);
  +
           cachedService = service;
           return service;
       }
  @@ -401,6 +425,26 @@
           context.startElement(WSDDConstants.SERVICE_QNAME, attrs);
           writeFlowsToContext(context);
           writeParamsToContext(context);
  +
  +        if (style == SOAPService.STYLE_DOCUMENT && qName2MethodMap != null) {
  +            Set qnames = qName2MethodMap.keySet();
  +            if (qnames != null) {
  +                Iterator i = qnames.iterator();
  +                while (i.hasNext()) {
  +                    QName elQName = (QName)i.next();
  +                    String methodName = (String)qName2MethodMap.get(elQName);
  +                    String elemName = context.qName2String(elQName);
  +                    attrs = new AttributesImpl();
  +                    attrs.addAttribute("", "method", "method",
  +                                       "CDATA", methodName);
  +                    attrs.addAttribute("", "element", "element",
  +                                       "CDATA", elemName);
  +
  +                    context.startElement(elMapQName, attrs);
  +                    context.endElement();
  +                }
  +            }
  +        }
   
           for (int i=0; i < typeMappings.size(); i++) {
               ((WSDDTypeMapping) typeMappings.elementAt(i)).writeToContext(context);
  
  
  
  1.48      +29 -2     xml-axis/java/src/org/apache/axis/handlers/soap/SOAPService.java
  
  Index: SOAPService.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/handlers/soap/SOAPService.java,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- SOAPService.java  22 Feb 2002 23:39:45 -0000      1.47
  +++ SOAPService.java  28 Feb 2002 13:37:47 -0000      1.48
  @@ -82,6 +82,7 @@
   import java.util.Enumeration;
   import java.util.Vector;
   import java.util.ArrayList;
  +import java.util.HashMap;
   import java.beans.IntrospectionException;
   
   /** A <code>SOAPService</code> is a Handler which encapsulates a SOAP
  @@ -115,7 +116,13 @@
        * Style of the service - document or RPC
        */ 
       private int style = STYLE_RPC;
  -    
  +
  +    /**
  +     * Mappings of element QNames -> method names if we're doc/literal and
  +     * not in wrapped mode.
  +     */
  +    private HashMap qName2MethodMap = null;
  +
       /**
        * SOAPRequestHandler is used to inject SOAP semantics just before
        * the pivot handler.
  @@ -266,7 +273,27 @@
       public void setStyle(int style) {
           this.style = style;
       }
  -    
  +
  +    public void setElementMap(HashMap elementMap) {
  +        this.qName2MethodMap = elementMap;
  +    }
  +
  +    /**
  +     * Retreive a method which has been mapped to a particular element
  +     * QName (for document/literal services)
  +     *
  +     * @param elementQName the QName of an XML element to dispatch on
  +     * @return a method which should handle the specified element, or
  +     *         null if no such method has been mapped.
  +     */
  +    public String getMethodForElementName(QName elementQName)
  +    {
  +        if (qName2MethodMap != null) {
  +            return (String)qName2MethodMap.get(elementQName);
  +        }
  +        return null;
  +    }
  +
       /*********************************************************************
        * Administration and management APIs
        *
  
  
  
  1.21      +29 -10    xml-axis/java/src/org/apache/axis/message/BodyBuilder.java
  
  Index: BodyBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/BodyBuilder.java,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -r1.20 -r1.21
  --- BodyBuilder.java  27 Feb 2002 17:32:17 -0000      1.20
  +++ BodyBuilder.java  28 Feb 2002 13:37:48 -0000      1.21
  @@ -73,6 +73,8 @@
   import org.xml.sax.Attributes;
   import org.xml.sax.SAXException;
   
  +import javax.xml.rpc.namespace.QName;
  +
   public class BodyBuilder extends SOAPHandler
   {
       protected static Log log =
  @@ -100,7 +102,8 @@
               log.debug(JavaUtils.getMessage("enter00", 
"BodyBuilder.onStartChild()"));
           }
           SOAPHandler handler = null;
  -        
  +        SOAPService service = null;
  +
           /** We're about to create a body element.  So we really need
            * to know at this point if this is an RPC service or not.  It's
            * possible that no one has set the service up until this point,
  @@ -115,19 +118,19 @@
           if ((root != null) && root.equals("0")) isRoot = false;
   
           MessageContext msgContext = context.getMessageContext();
  +        service = msgContext.getService();
   
           if (isRoot &&
  -            msgContext.getService() == null) {
  +            service == null) {
   
               if (log.isDebugEnabled()) {
                   log.debug(JavaUtils.getMessage("dispatching00",namespace));
               }
   
               try {
  -                SOAPService service = msgContext.
  -                                           getAxisEngine().
  -                                           getConfig().
  -                                           getServiceByNamespaceURI(namespace);
  +                service = msgContext.getAxisEngine().
  +                                     getConfig().
  +                                     getServiceByNamespaceURI(namespace);
                   if (service != null)
                       msgContext.setService(service);
               } catch (ConfigurationException e) {
  @@ -146,13 +149,29 @@
                                              attributes, context);
               handler = new SOAPFaultBuilder((SOAPFaultElement)element,
                                              context);
  -        } else if (!gotRPCElement &&
  -            isRoot && 
  -            msgContext.isEncoded() ) {
  +        } else if (!gotRPCElement) {
  +            if (isRoot &&
  +                msgContext.isEncoded() ) {
                   gotRPCElement = true;
                   element = new RPCElement(namespace, localName, prefix,
                                            attributes, context);
  -        } else {
  +            } else {
  +                // If we can figure out a method based on the element name,
  +                // we must want an RPCElement.  !!! This needs cleaning up
  +                //
  +                if (service != null) {
  +                    QName qname = new QName(namespace, localName);
  +                    String method = service.getMethodForElementName(qname);
  +                    if (method != null) {
  +                        element = new RPCElement(namespace, localName, prefix,
  +                                                 attributes, context);
  +                        gotRPCElement = true;
  +                    }
  +                }
  +            }
  +        }
  +
  +        if (element == null) {
               element = new SOAPBodyElement(namespace, localName, prefix,
                                         attributes, context);
               if (element.getFixupDeserializer() != null)
  
  
  
  1.37      +28 -4     xml-axis/java/src/org/apache/axis/message/RPCElement.java
  
  Index: RPCElement.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/message/RPCElement.java,v
  retrieving revision 1.36
  retrieving revision 1.37
  diff -u -r1.36 -r1.37
  --- RPCElement.java   27 Feb 2002 13:41:28 -0000      1.36
  +++ RPCElement.java   28 Feb 2002 13:37:48 -0000      1.37
  @@ -76,7 +76,8 @@
   {
       protected Vector params = new Vector();
       protected boolean needDeser = false;
  -    
  +    protected boolean elementIsFirstParam = false;
  +
       public RPCElement(String namespace, String localName, String prefix,
                         Attributes attributes, DeserializationContext context)
       {
  @@ -86,6 +87,24 @@
           
           // This came from parsing XML, so we need to deserialize it sometime
           needDeser = true;
  +
  +        // IF we're doc/literal... we can't count on the element name
  +        // being the method name.
  +        SOAPService service = context.getMessageContext().getService();
  +        if (service != null && service.getStyle() == SOAPService.STYLE_DOCUMENT) {
  +            // So see if we can map it using metadata
  +            QName qname = new QName(namespace, localName);
  +            String methodName = service.getMethodForElementName(qname);
  +            if (methodName != null) {
  +                this.name = methodName;
  +
  +                // OK, now that we've found a match, we need to note that
  +                // we should start at this level when deserializing
  +                // "parameters"
  +                elementIsFirstParam = true;
  +
  +            }
  +        }
       }
       
       public RPCElement(String namespace, String methodName, Object [] args)
  @@ -159,9 +178,14 @@
                       defaultParamTypes = method[i].getParameterTypes();
                       if (defaultParamTypes.length >= numChildren) {
                           try {
  -                            context.pushElementHandler(new EnvelopeHandler(new 
RPCHandler(this)));
  -                            context.setCurElement(this);
  -        
  +                            if (elementIsFirstParam) {
  +                                context.pushElementHandler(new RPCHandler(this));
  +                                context.setCurElement(null);
  +                            } else {
  +                                context.pushElementHandler(new EnvelopeHandler(new 
RPCHandler(this)));
  +                                context.setCurElement(this);
  +                            }
  +
                               publishToHandler((org.xml.sax.ContentHandler) context);
                           } catch (SAXException e) {
                               // If there was a problem, try the next one.
  
  
  
  1.44      +21 -0     xml-axis/java/src/org/apache/axis/utils/XMLUtils.java
  
  Index: XMLUtils.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/src/org/apache/axis/utils/XMLUtils.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- XMLUtils.java     22 Feb 2002 23:39:47 -0000      1.43
  +++ XMLUtils.java     28 Feb 2002 13:37:48 -0000      1.44
  @@ -365,6 +365,27 @@
       }
   
       /**
  +     * Return a string for a particular QName, mapping a new prefix
  +     * if necessary.
  +     */
  +    public String getStringForQName(QName qname, Element e)
  +    {
  +        String uri = qname.getNamespaceURI();
  +        String prefix = getPrefix(uri, e);
  +        if (prefix == null) {
  +            int i = 1;
  +            prefix = "ns" + i;
  +            while (getNamespace(prefix, e) != null) {
  +                i++;
  +                prefix = "ns" + i;
  +            }
  +            e.setAttributeNS(Constants.NS_URI_XMLNS,
  +                        "xmlns:" + prefix, uri);
  +        }
  +        return prefix + ":" + qname.getLocalPart();
  +    }
  +
  +    /**
        * Gather all existing prefixes in use in this document
        *
        */
  
  
  


Reply via email to