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
*
*/