Author: sumedha
Date: Wed Nov 12 12:14:03 2008
New Revision: 713490

URL: http://svn.apache.org/viewvc?rev=713490&view=rev
Log:
more support for accepting request messages from IM clients & sending back the 
responses. Now we have fully functional code to test this scenario. However 
error handling needs to be improved. Committing with TODOs

Modified:
    
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/XMPPSender.java
    
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPConstants.java
    
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPPacketListener.java

Modified: 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/XMPPSender.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/XMPPSender.java?rev=713490&r1=713489&r2=713490&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/XMPPSender.java
 (original)
+++ 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/XMPPSender.java
 Wed Nov 12 12:14:03 2008
@@ -19,16 +19,18 @@
 
 package org.apache.axis2.transport.xmpp;
 
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 
+import javax.xml.namespace.QName;
+
 import org.apache.axiom.om.OMElement;
 import org.apache.axis2.AxisFault;
 import org.apache.axis2.Constants;
 import org.apache.axis2.client.Options;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisMessage;
 import org.apache.axis2.description.AxisOperation;
 import org.apache.axis2.description.AxisService;
 import org.apache.axis2.description.Parameter;
@@ -44,8 +46,16 @@
 import org.apache.axis2.transport.xmpp.util.XMPPServerCredentials;
 import org.apache.axis2.transport.xmpp.util.XMPPUtils;
 import org.apache.axis2.util.Utils;
+import org.apache.axis2.wsdl.WSDLConstants;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.ws.commons.schema.XmlSchemaAll;
+import org.apache.ws.commons.schema.XmlSchemaComplexType;
+import org.apache.ws.commons.schema.XmlSchemaElement;
+import org.apache.ws.commons.schema.XmlSchemaGroupBase;
+import org.apache.ws.commons.schema.XmlSchemaParticle;
+import org.apache.ws.commons.schema.XmlSchemaSequence;
+import org.apache.ws.commons.schema.XmlSchemaType;
 import org.jivesoftware.smack.Chat;
 import org.jivesoftware.smack.ChatManager;
 import org.jivesoftware.smack.XMPPConnection;
@@ -187,11 +197,31 @@
                                WSDL2Constants.MEP_URI_OUT_IN.equals(
                                                
msgCtx.getOperationContext().getAxisOperation().getMessageExchangePattern());
                        
-                       OMElement msgElement = msgCtx.getEnvelope();            
        
-                       String soapMessage = msgElement.toString();
                        //int endOfXMLDeclaration = soapMessage.indexOf("?>");
                        //String modifiedSOAPMessage = 
soapMessage.substring(endOfXMLDeclaration+2);
-                       message.setBody(soapMessage);                           
+
+                       OMElement msgElement;                   
+                       String messageToBeSent = "";
+                       
+                       //TODO : need to read from a constant
+                       
if("xmpp/text".equals(xmppOutTransportInfo.getContentType())){
+                               //if request is received from a chat client, 
whole soap envelope
+                               //should not be sent.
+                               OMElement soapBodyEle = 
msgCtx.getEnvelope().getBody();
+                               OMElement responseEle = 
soapBodyEle.getFirstElement();
+                               if(responseEle != null){
+                                       msgElement = 
responseEle.getFirstElement();                                     
+                               }else{
+                                       msgElement = responseEle;
+                               }
+                       }else{
+                               //if request received from a ws client whole 
soap envelope 
+                               //must be sent.
+                               msgElement = msgCtx.getEnvelope();
+                       }       
+                       messageToBeSent = msgElement.toString();
+                       message.setBody(messageToBeSent);
+                       
                        
                        XMPPClientSidePacketListener 
xmppClientSidePacketListener = null;
                        if(waitForResponse && !msgCtx.isServerSide()){
@@ -236,22 +266,21 @@
        Object obj = msgCtx.getProperty(XMPPConstants.MESSAGE_FROM_CHAT);
        if(obj != null){
                String message = (String)obj;
-               String response = "";
-               if(("help".compareToIgnoreCase(message.trim()) == 0)
-                               || "?".equals(message)){
-                       response = prepareHelpTextForChat();                    
-               }else if("listServices".equals(message.trim())){
-                       response = prepareServicesList(msgCtx);                 
-               }else if (message.trim().startsWith("getOperations")){
-                       response = prepareOperationList(msgCtx,message);
+               String response = "";           
+               
+               if(message.trim().startsWith("help")){
+                       response = prepareHelpTextForChat();                    
                        
+               }else if(message.trim().startsWith("listServices")){
+                       response = prepareServicesList(msgCtx);
+               }else if (message.trim().startsWith("getOperations")){
+                       response = prepareOperationList(msgCtx,message);
                }else{
                        //TODO add support for more help commands
                }
-               sendChatMessage(msgCtx,response);               
+               sendChatMessage(msgCtx,response);               
        }
-    }
-
-    
+    }    
+   
     /**
      * Prepares a list of service names deployed in current runtime
      * @param msgCtx
@@ -272,13 +301,7 @@
                        int index = 1;
                        while(itrOperations.hasNext()){
                                AxisOperation operation = 
(AxisOperation)itrOperations.next();
-                               //ArrayList params = operation.getParameters();
-                               //Iterator itrParams = params.iterator();
-                               String parameterList = "";
-                               //while(itrParams.hasNext()){
-                               //      Parameter param = (Parameter) 
itrParams.next();
-                               //      parameterList = param.getName()+",";
-                               //}
+                               String parameterList = 
getParameterListForOperation(operation);                         
                                sb.append(index 
+"."+operation.getName().getLocalPart()+"("+parameterList+")"+"\n");
                                index++;
                        }
@@ -289,6 +312,47 @@
                return sb.toString();
        }
 
+       /**
+        * Retrieves list of parameter names & their type for a given operation
+        * @param operation
+        */
+       private static String getParameterListForOperation(AxisOperation 
operation) {
+               //Logic copied from BuilderUtil.buildsoapMessage(...)
+               StringBuffer paramList = new StringBuffer();
+               AxisMessage axisMessage =
+                   operation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
+               XmlSchemaElement xmlSchemaElement = 
axisMessage.getSchemaElement();
+               if(xmlSchemaElement != null){                   
+                   XmlSchemaType schemaType = xmlSchemaElement.getSchemaType();
+                   if (schemaType instanceof XmlSchemaComplexType) {
+                       XmlSchemaComplexType complexType = 
((XmlSchemaComplexType)schemaType);
+                       XmlSchemaParticle particle = complexType.getParticle();
+                       if (particle instanceof XmlSchemaSequence || particle 
instanceof XmlSchemaAll) {
+                           XmlSchemaGroupBase xmlSchemaGroupBase = 
(XmlSchemaGroupBase)particle;
+                           Iterator iterator = 
xmlSchemaGroupBase.getItems().getIterator();
+
+                           while (iterator.hasNext()) {
+                               XmlSchemaElement innerElement = 
(XmlSchemaElement)iterator.next();
+                               QName qName = innerElement.getQName();
+                               if (qName == null && 
innerElement.getSchemaTypeName()
+                                       
.equals(org.apache.ws.commons.schema.constants.Constants.XSD_ANYTYPE)) {
+                                   break;
+                               }
+                               long minOccurs = innerElement.getMinOccurs();
+                               boolean nillable = innerElement.isNillable();
+                               String name =
+                                       qName != null ? qName.getLocalPart() : 
innerElement.getName();
+                               String type = 
innerElement.getSchemaTypeName().toString();
+                               paramList.append(","+type +" " +name);
+                           }
+                       }
+                  }                    
+               }
+               //remove first ","
+               String list = paramList.toString();             
+               return list.replaceFirst(",", "");
+       }
+
        
     /**
      * Prepares a list of service names deployed in current runtime

Modified: 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPConstants.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPConstants.java?rev=713490&r1=713489&r2=713490&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPConstants.java
 (original)
+++ 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPConstants.java
 Wed Nov 12 12:14:03 2008
@@ -49,5 +49,5 @@
     //This is set to true, if a request message is sent through XMPPSender
     //Used to distinguish messages coming from chat clients.
     public static final String CONTAINS_SOAP_ENVELOPE = 
"transport.xmpp.containsSOAPEnvelope";
-    public static final String MESSAGE_FROM_CHAT = 
"transport.xmpp.message.from.chat";
+    public static final String MESSAGE_FROM_CHAT = 
"transport.xmpp.message.from.chat";   
 }

Modified: 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPPacketListener.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPPacketListener.java?rev=713490&r1=713489&r2=713490&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPPacketListener.java
 (original)
+++ 
webservices/commons/trunk/modules/transport/modules/xmpp/src/org/apache/axis2/transport/xmpp/util/XMPPPacketListener.java
 Wed Nov 12 12:14:03 2008
@@ -19,13 +19,26 @@
 
 package org.apache.axis2.transport.xmpp.util;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.util.concurrent.Executor;
+
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
 import org.apache.axiom.om.OMException;
 import org.apache.axiom.soap.SOAPEnvelope;
+import org.apache.axiom.soap.SOAPFactory;
+import org.apache.axiom.soap.impl.llom.soap11.SOAP11Factory;
 import org.apache.axis2.AxisFault;
 import org.apache.axis2.Constants;
 import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.builder.BuilderUtil;
 import org.apache.axis2.context.ConfigurationContext;
 import org.apache.axis2.context.MessageContext;
+import org.apache.axis2.description.AxisOperation;
 import org.apache.axis2.description.AxisService;
 import org.apache.axis2.description.TransportInDescription;
 import org.apache.axis2.description.TransportOutDescription;
@@ -33,6 +46,7 @@
 import org.apache.axis2.transport.TransportUtils;
 import org.apache.axis2.transport.xmpp.XMPPSender;
 import org.apache.axis2.util.MessageContextBuilder;
+import org.apache.axis2.util.MultipleEntryHashMap;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -40,13 +54,6 @@
 import org.jivesoftware.smack.packet.Message;
 import org.jivesoftware.smack.packet.Packet;
 
-import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.stream.XMLStreamException;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.concurrent.Executor;
-
 public class XMPPPacketListener implements PacketListener {
        private static final Log log = 
LogFactory.getLog(XMPPPacketListener.class);
        private XMPPConnectionFactory xmppConnectionFactory = null;
@@ -166,16 +173,21 @@
                }
                
                InputStream inputStream = new 
ByteArrayInputStream(messageBody.getBytes());
-               SOAPEnvelope envelope;
+               SOAPEnvelope envelope = null;
                try {
                        Object obj = 
message.getProperty(XMPPConstants.CONTAINS_SOAP_ENVELOPE); 
                        if(obj != null && ((Boolean)obj).booleanValue()){
                                envelope = 
TransportUtils.createSOAPMessage(msgContext, inputStream, "text/xml");
-                               msgContext.setEnvelope(envelope);
                                
msgContext.setProperty(XMPPConstants.CONTAINS_SOAP_ENVELOPE, new Boolean(true));
                        }else{
-                               //A text message has been received from a chat 
client, send it along with message context
-                               
msgContext.setProperty(XMPPConstants.MESSAGE_FROM_CHAT, messageBody);
+                               //A text message has been received from a chat 
client
+                               //This message could either be a service call 
or a help command
+                               
if(!(messageContainsCommandsFromChat(messageBody,msgContext))){
+                                       envelope = 
createSOAPEnvelopeForRawMessage(msgContext, messageBody);                       
             
+                               }                               
+                       }
+                       if(envelope != null){
+                               msgContext.setEnvelope(envelope);               
                
                        }
                }catch (OMException e) {
                        log.error(logMsg, e);
@@ -192,6 +204,94 @@
                }
        }
 
+       /**
+        * In the direct chat client scenario, client can send commands & 
retrieve details
+        * on available services, operations,etc. This method checks if a 
client has sent
+        * such command. Only limited set of commands are available as of now. 
+        * @param message
+        * @param msgContext
+        * @return
+        */
+       private boolean messageContainsCommandsFromChat(String 
message,MessageContext msgContext){
+               boolean containsKnownCommand = false;
+               if(message.trim().startsWith("help")){
+                       containsKnownCommand = true;                            
                
+               }else if(message.trim().startsWith("listServices")){
+                       containsKnownCommand = true;
+               }else if (message.trim().startsWith("getOperations")){
+                       containsKnownCommand = true;
+               }
+               
+               if(containsKnownCommand){
+                       
msgContext.setProperty(XMPPConstants.MESSAGE_FROM_CHAT,message.trim()); 
+               }
+               return containsKnownCommand;
+       }
+       
+       /**
+        * Creates a SOAP envelope using details found in chat message.
+        * @param msgCtx
+        * @param chatMessage
+        * @return
+        */
+       private SOAPEnvelope createSOAPEnvelopeForRawMessage(MessageContext 
msgCtx,String chatMessage)
+       throws AxisFault{
+               //TODO : need to add error handling logic 
+       String callRemoved = chatMessage.replaceFirst("call", "");
+       //extract Service name
+       String serviceName = callRemoved.trim().substring(0, 
callRemoved.indexOf(":")-1);
+       String operationName = 
callRemoved.trim().substring(callRemoved.indexOf(":"), 
callRemoved.indexOf("(")-1);
+
+       //Extract parameters from IM message
+       String parameterList = 
callRemoved.trim().substring(callRemoved.indexOf("("),callRemoved.trim().length()-1);
    
+       StringTokenizer st = new StringTokenizer(parameterList,",");
+               MultipleEntryHashMap parameterMap = new MultipleEntryHashMap();
+       while(st.hasMoreTokens()){
+               String token = st.nextToken();
+               String name = token.substring(0, token.indexOf("="));
+               String value = token.substring(token.indexOf("=")+1);
+               parameterMap.put(name, value);
+       }
+       
+               SOAPEnvelope envelope = null;
+               try {
+                       
msgCtx.setProperty(XMPPConstants.CONTAINS_SOAP_ENVELOPE, new Boolean(true));
+                       if(serviceName != null && serviceName.trim().length() > 
0){
+                               AxisService axisService = 
msgCtx.getConfigurationContext().getAxisConfiguration().getService(serviceName);
+                               msgCtx.setAxisService(axisService);     
+                               
+                               AxisOperation axisOperation = 
axisService.getOperationBySOAPAction("urn:"+operationName);
+                               if(axisOperation != null){
+                                       msgCtx.setAxisOperation(axisOperation);
+                               }
+                       }
+               
+                       if(operationName != null && 
operationName.trim().length() > 0){
+                               msgCtx.setSoapAction("urn:"+operationName);
+                       }
+                       
+                       XMPPOutTransportInfo xmppOutTransportInfo = 
(XMPPOutTransportInfo)msgCtx.getProperty(
+                                       
org.apache.axis2.Constants.OUT_TRANSPORT_INFO);
+                       //This should be only set for messages received via 
chat.
+                       //TODO : need to read from a constant
+                       xmppOutTransportInfo.setContentType("xmpp/text");
+                       
+                       msgCtx.setServerSide(true);
+                       
+                       //TODO : need to support SOAP12 as well
+                       SOAPFactory soapFactory = new SOAP11Factory();
+                       envelope = BuilderUtil.buildsoapMessage(msgCtx, 
parameterMap,
+                    soapFactory);
+                       //TODO : improve error handling & messages
+               } catch (AxisFault e) {
+                       throw new AxisFault(e.getMessage());
+               } catch (OMException e) {
+                       throw new AxisFault(e.getMessage());
+               } catch (FactoryConfigurationError e) {
+                       throw new AxisFault(e.getMessage());
+               }               
+               return envelope;
+       }
 
        /**
         * The actual Runnable Worker implementation which will process the
@@ -215,7 +315,7 @@
                                                AxisEngine.receive(msgCtx);
                                        }                                       
                                }else{
-                                       //Send a text reply message to chat 
client
+                                       //Send a text reply message to command 
received from chat client
                                        XMPPSender.processChatMessage(msgCtx);
                                }
                        } catch (AxisFault e) {
@@ -232,4 +332,4 @@
                        }
                }
        }
-}
+}
\ No newline at end of file


Reply via email to