Package org.apache.axis2.transport.xmpp

Source Code of org.apache.axis2.transport.xmpp.XMPPSender

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package org.apache.axis2.transport.xmpp;

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;
import org.apache.axis2.description.TransportOutDescription;
import org.apache.axis2.description.WSDL2Constants;
import org.apache.axis2.handlers.AbstractHandler;
import org.apache.axis2.transport.OutTransportInfo;
import org.apache.axis2.transport.TransportSender;
import org.apache.axis2.transport.xmpp.util.XMPPClientSidePacketListener;
import org.apache.axis2.transport.xmpp.util.XMPPConnectionFactory;
import org.apache.axis2.transport.xmpp.util.XMPPConstants;
import org.apache.axis2.transport.xmpp.util.XMPPOutTransportInfo;
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;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;

public class XMPPSender extends AbstractHandler implements TransportSender {
  static Log log = null;
    XMPPConnectionFactory connectionFactory;
    XMPPServerCredentials serverCredentials;   
 
    public XMPPSender() {
        log = LogFactory.getLog(XMPPSender.class);
    }
   
  public void cleanup(MessageContext msgContext) throws AxisFault
  }

    /**
     * Initialize the transport sender by reading pre-defined connection factories for
     * outgoing messages. These will create sessions (one per each destination dealt with)
     * to be used when messages are being sent.
     * @param confContext the configuration context
     * @param transportOut the transport sender definition from axis2.xml
     * @throws AxisFault on error
     */ 
  public void init(ConfigurationContext confContext,
      TransportOutDescription transportOut) throws AxisFault {
    //if connection details are available from axis configuration
    //use those & connect to jabber server(s)
    serverCredentials = new XMPPServerCredentials();
    getConnectionDetailsFromAxisConfiguration(transportOut);   
    connectionFactory = new XMPPConnectionFactory();
    connectionFactory.connect(serverCredentials);   
  }

  /**
   * Extract connection details from Client options
   * @param msgCtx
   */
  private void connectUsingClientOptions(MessageContext msgCtx) throws AxisFault{   
    getConnectionDetailsFromClientOptions(msgCtx);
    connectionFactory = new XMPPConnectionFactory();
    connectionFactory.connect(serverCredentials);
  }
 
  public void stop() {}

  public InvocationResponse invoke(MessageContext msgContext)
      throws AxisFault {
        String targetAddress = (String) msgContext.getProperty(
                Constants.Configuration.TRANSPORT_URL);
            if (targetAddress != null) {
                sendMessage(msgContext, targetAddress, null);
            } else if (msgContext.getTo() != null && !msgContext.getTo().hasAnonymousAddress()) {
                targetAddress = msgContext.getTo().getAddress();

                if (!msgContext.getTo().hasNoneAddress()) {
                    sendMessage(msgContext, targetAddress, null);
                } else {
                    //Don't send the message.
                    return InvocationResponse.CONTINUE;
                }
            } else if (msgContext.isServerSide()) {
                // get the out transport info for server side when target EPR is unknown
                sendMessage(msgContext, null,
                    (OutTransportInfo) msgContext.getProperty(Constants.OUT_TRANSPORT_INFO));
            }
            return InvocationResponse.CONTINUE;
  }

    /**
     * Send the given message over XMPP transport
     *
     * @param msgCtx the axis2 message context
     * @throws AxisFault on error
     */
    public void sendMessage(MessageContext msgCtx, String targetAddress,
        OutTransportInfo outTransportInfo) throws AxisFault {
    XMPPConnection xmppConnection = null;
    XMPPOutTransportInfo xmppOutTransportInfo = null;
   
    //if on client side,create connection to xmpp server
    if(!msgCtx.isServerSide()){
      connectUsingClientOptions(msgCtx);
    }
   
    Message message = new Message();
    Options options = msgCtx.getOptions();     
      String serviceName = XMPPUtils.getServiceName(targetAddress);     
     
    if (targetAddress != null) {
      xmppOutTransportInfo = new XMPPOutTransportInfo(targetAddress);
      xmppOutTransportInfo.setConnectionFactory(connectionFactory);
    } else if (msgCtx.getTo() != null &&
        !msgCtx.getTo().hasAnonymousAddress()) {
      //TODO
    } else if (msgCtx.isServerSide()) {
      xmppOutTransportInfo = (XMPPOutTransportInfo)
      msgCtx.getProperty(Constants.OUT_TRANSPORT_INFO);
    }
     
    xmppConnection = xmppOutTransportInfo.getConnectionFactory().getXmppConnection();   
   
    if(msgCtx.isServerSide()){
      message.setProperty(XMPPConstants.IS_SERVER_SIDE, new Boolean(false));
      message.setProperty(XMPPConstants.IN_REPLY_TO, xmppOutTransportInfo.getInReplyTo());
    }else{
      //message is going to be processed on server side
      message.setProperty(XMPPConstants.IS_SERVER_SIDE,new Boolean(true));
      //we are sending a soap envelope as a message
      message.setProperty(XMPPConstants.CONTAINS_SOAP_ENVELOPE, new Boolean(true));
      message.setProperty(XMPPConstants.SERVICE_NAME, serviceName);
      String action = options.getAction();
      if (action == null) {
        AxisOperation axisOperation = msgCtx.getAxisOperation();
        if (axisOperation != null) {
          action = axisOperation.getSoapAction();
        }
      }
      if (action != null) {
        message.setProperty(XMPPConstants.ACTION, action);
      }
    }   
      if(xmppConnection == null){
        handleException("Connection to XMPP Server is not established.");       
      }
   
    //initialize the chat manager using connection
    ChatManager chatManager = xmppConnection.getChatManager();
    Chat chat = chatManager.createChat(xmppOutTransportInfo.getDestinationAccount(), null);   
   
    try
    {
      boolean waitForResponse =
        msgCtx.getOperationContext() != null &&
        WSDL2Constants.MEP_URI_OUT_IN.equals(
            msgCtx.getOperationContext().getAxisOperation().getMessageExchangePattern());
     
      //int endOfXMLDeclaration = soapMessage.indexOf("?>");
      //String modifiedSOAPMessage = soapMessage.substring(endOfXMLDeclaration+2);

      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()){
        PacketFilter filter = new PacketTypeFilter(message.getClass());       
        xmppClientSidePacketListener = new XMPPClientSidePacketListener(msgCtx);
        xmppConnection.addPacketListener(xmppClientSidePacketListener,filter);
      }     

      chat.sendMessage(message);
      log.debug("Sent message :"+message.toXML());

      //If this is on client side, wait for the response from server.
      //Is this the best way to do this?
      if(waitForResponse && !msgCtx.isServerSide()){
        //TODO : need to add a timeout
        while(! xmppClientSidePacketListener.isResponseReceived()){
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            log.debug("Sleep interrupted",e);
          }   
        }
        xmppConnection.disconnect();
      }

    } catch (XMPPException e) {
      log.error("Error occurred while sending the message : "+message.toXML(),e);
      handleException("Error occurred while sending the message : "+message.toXML(),e);
    }finally{
      if(!msgCtx.isServerSide()){
        xmppConnection.disconnect();
      }
    }
    } 
   
    /**
     * Process message requests that came in through chat clients
     * @param msgCtx
     * @throws AxisFault
     */
    public static void processChatMessage(MessageContext msgCtx) throws AxisFault {
      Object obj = msgCtx.getProperty(XMPPConstants.MESSAGE_FROM_CHAT);
      if(obj != null){
          String message = (String)obj;
          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);        
      }
    }   
  
    /**
     * Prepares a list of service names deployed in current runtime
     * @param msgCtx
     * @return
     */
  private static String prepareOperationList(MessageContext msgCtx,String chatMessage) {
    StringBuffer sb = new StringBuffer();
    //extract service name
    String serviceName = chatMessage.replace("getOperations", "");
    serviceName = serviceName.replaceAll(" ", "");
    if(log.isDebugEnabled()){
      log.debug("Finding operations for service :"+ serviceName)
    }
   
    try {
      AxisService service = msgCtx.getConfigurationContext().getAxisConfiguration().getService(serviceName);
      Iterator itrOperations = service.getOperations();
      int index = 1;
      while(itrOperations.hasNext()){
        AxisOperation operation = (AxisOperation)itrOperations.next();
        String parameterList = getParameterListForOperation(operation);       
        sb.append(index +"."+operation.getName().getLocalPart()+"("+parameterList+")"+"\n");
        index++;
      }
    } catch (AxisFault e) {
      log.error("Error occurred while retreiving AxisService : "+serviceName,e);
      sb.append("Error occurred while retrieving operations for service : "+serviceName);
    }   
    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
     * @param msgCtx
     * @return
     */
  private static String prepareServicesList(MessageContext msgCtx) {
    HashMap services = msgCtx.getConfigurationContext().getAxisConfiguration().getServices();
    StringBuffer sb = new StringBuffer();
    if(services != null && services.size() > 0){
      Iterator itrServiceNames = services.keySet().iterator();     
      int index = 1;
      while (itrServiceNames.hasNext()) {
        String serviceName = (String) itrServiceNames.next();
        sb.append(index+"."+serviceName+"\n");
        index++;
      }
    }
    return sb.toString();
  }
   
   
    /**
     * Generate help text for chat client
     * @return {@link String}
     */
    private static String prepareHelpTextForChat(){
      StringBuffer helpText = new StringBuffer();
      helpText.append("Following commands are supported :"+"\n");
      helpText.append("-----------------------------------"+"\n");
      helpText.append("1. listServices"+"\n");
      helpText.append("2. getOperations <service-name>"+"\n");
      helpText.append("3. call <service-name>:<operation>(<param1>,<param2>,...)"+"\n");
      return helpText.toString();
    }
   
    /**
     * Replies to IM clients via a chat message. The reply contains the invocation response as a string.
     * @param msgCtx
     * @param responseMsg
     * @throws AxisFault
     */
    private static void sendChatMessage(MessageContext msgCtx,String responseMsg) throws AxisFault {
        XMPPConnection xmppConnection = null;
        XMPPOutTransportInfo xmppOutTransportInfo = null;       
        Message message = new Message();
         
         xmppOutTransportInfo = (XMPPOutTransportInfo)msgCtx.getProperty(Constants.OUT_TRANSPORT_INFO);
         if(xmppOutTransportInfo != null){
           message.setProperty(XMPPConstants.IN_REPLY_TO, xmppOutTransportInfo.getInReplyTo());
             xmppConnection = xmppOutTransportInfo.getConnectionFactory().getXmppConnection();
               if(xmppConnection == null){
                 handleException("Connection to XMPP Server is not established.");       
               }            
         }else{
           handleException("Could not find message sender details.");
         }        
       
        //initialize the chat manager using connection
        ChatManager chatManager = xmppConnection.getChatManager();
        Chat chat = chatManager.createChat(xmppOutTransportInfo.getDestinationAccount(), null);       
        try{        
           message.setBody(responseMsg);   
          chat.sendMessage(message);
          log.debug("Sent message :"+message.toXML());
        } catch (XMPPException e) {
          XMPPSender.handleException("Error occurred while sending the message : "+message.toXML(),e);
        }
        } 

    /**
     * Extract connection details from axis2.xml's transportsender section
     * @param serverCredentials
     * @param transportOut
     */
    private void getConnectionDetailsFromAxisConfiguration(TransportOutDescription transportOut){
      if(transportOut != null){
      Parameter serverUrl = transportOut.getParameter(XMPPConstants.XMPP_SERVER_URL);
      if (serverUrl != null) {
        serverCredentials.setServerUrl(Utils.getParameterValue(serverUrl));
      }
     
      Parameter userName = transportOut.getParameter(XMPPConstants.XMPP_SERVER_USERNAME);
      if (userName != null) {
        serverCredentials.setAccountName(Utils.getParameterValue(userName));
      }
   
      Parameter password = transportOut.getParameter(XMPPConstants.XMPP_SERVER_PASSWORD);
      if (password != null) {
        serverCredentials.setPassword(Utils.getParameterValue(password));
      }

      Parameter serverType = transportOut.getParameter(XMPPConstants.XMPP_SERVER_TYPE);     
      if (serverType != null) {
        serverCredentials.setServerType(Utils.getParameterValue(serverType));
      }     
    }
  }
 
  /**
   * Extract connection details from client options
   * @param serverCredentials
   * @param msgContext
   */
    private void getConnectionDetailsFromClientOptions(MessageContext msgContext){
      Options clientOptions = msgContext.getOptions();

    if (clientOptions.getProperty(XMPPConstants.XMPP_SERVER_USERNAME) != null){
      serverCredentials.setAccountName((String)clientOptions.getProperty(XMPPConstants.XMPP_SERVER_USERNAME));
    }
    if (clientOptions.getProperty(XMPPConstants.XMPP_SERVER_PASSWORD) != null){
      serverCredentials.setPassword((String)clientOptions.getProperty(XMPPConstants.XMPP_SERVER_PASSWORD));
    }
    if (clientOptions.getProperty(XMPPConstants.XMPP_SERVER_URL) != null){
      serverCredentials.setServerUrl((String)clientOptions.getProperty(XMPPConstants.XMPP_SERVER_URL));
    }
    if (clientOptions.getProperty(XMPPConstants.XMPP_SERVER_TYPE) != null){
      serverCredentials.setServerType((String)clientOptions.getProperty(XMPPConstants.XMPP_SERVER_TYPE));
    }   
  } 
 
    private static void handleException(String msg, Exception e) throws AxisFault {
        log.error(msg, e);
        throw new AxisFault(msg, e);
    }
    private static void handleException(String msg) throws AxisFault {
        log.error(msg);
        throw new AxisFault(msg);
    }
}
TOP

Related Classes of org.apache.axis2.transport.xmpp.XMPPSender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.