Package org.xmlBlaster.client.dispatch

Source Code of org.xmlBlaster.client.dispatch.ClientDispatchConnection

/*------------------------------------------------------------------------------
Name:      ClientDispatchConnection.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/
package org.xmlBlaster.client.dispatch;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.xmlBlaster.util.Global;
import org.xmlBlaster.util.IsoDateParser;
import org.xmlBlaster.util.SessionName;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.checkpoint.I_Checkpoint;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.def.MethodName;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.queuemsg.MsgQueueEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueConnectEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueDisconnectEntry;
import org.xmlBlaster.client.queuemsg.MsgQueuePublishEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueSubscribeEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueUnSubscribeEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueEraseEntry;
import org.xmlBlaster.client.queuemsg.MsgQueueGetEntry;
import org.xmlBlaster.util.dispatch.DispatchConnection;
import org.xmlBlaster.util.qos.ConnectQosData;
import org.xmlBlaster.client.qos.ConnectQos;
import org.xmlBlaster.client.qos.ConnectReturnQos;
import org.xmlBlaster.client.qos.PublishReturnQos;
import org.xmlBlaster.client.qos.SubscribeReturnQos;
import org.xmlBlaster.client.qos.UnSubscribeReturnQos;
import org.xmlBlaster.client.qos.EraseReturnQos;
import org.xmlBlaster.client.protocol.I_XmlBlasterConnection;
import org.xmlBlaster.client.protocol.ProtocolPluginManager;
import org.xmlBlaster.util.qos.address.Address;
import org.xmlBlaster.util.qos.address.AddressBase;
import org.xmlBlaster.util.xbformat.I_ProgressListener;
import org.xmlBlaster.util.MsgUnit;
import org.xmlBlaster.util.MsgUnitRaw;
import org.xmlBlaster.authentication.plugins.CryptDataHolder;
import org.xmlBlaster.authentication.plugins.I_MsgSecurityInterceptor;


/**
* Holding all necessary infos to establish callback
* connections and invoke their update().
* @see DispatchConnection
* @author xmlBlaster@marcelruff.info
*/
public final class ClientDispatchConnection extends DispatchConnection
{
   private static Logger log = Logger.getLogger(ClientDispatchConnection.class.getName());
   private final String ME;
   private I_XmlBlasterConnection driver;
   private final I_MsgSecurityInterceptor securityInterceptor;
   private ConnectQosData connectQosData;
   private ConnectReturnQos connectReturnQos;
   private String[] checkPointContext;
   private MsgQueueEntry connectEntry;
   private SessionName sessionName;

   /**
    * @param connectionsHandler The DevliveryConnectionsHandler witch i belong to
    * @param aAddress The address i shall connect to
    */
   public ClientDispatchConnection(Global glob, ClientDispatchConnectionsHandler connectionsHandler, AddressBase address) throws XmlBlasterException {
      super(glob, connectionsHandler, address);
      this.ME = "ClientDispatchConnection-" + connectionsHandler.getDispatchManager().getQueue().getStorageId();
      this.securityInterceptor = connectionsHandler.getDispatchManager().getMsgSecurityInterceptor();
   }

   public final String getDriverName() {
      return (this.driver != null) ? this.driver.getProtocol() : "unknown";
   }

   /**
    * @return A nice name for logging
    */
   public final String getName() {
      return ME;
   }

   /**
    * Load the appropriate protocol driver, e.g the CORBA protocol plugin.
    * <p>
    * This method is called by our base class during initialization.
    * </p>
    */
   public final void loadPlugin() throws XmlBlasterException {
      ProtocolPluginManager loader = glob.getProtocolPluginManager();
      this.driver = loader.getPlugin(super.address.getType(), super.address.getVersion()); // e.g. CorbaConnection(glob);
      if (this.driver == null)
         throw new XmlBlasterException(glob, ErrorCode.RESOURCE_CONFIGURATION_PLUGINFAILED, ME, "Sorry, protocol type='" + super.address.getType() + "' is not supported");
   }

   /**
    * @see DispatchConnection#connectLowlevel()
    */
   public final void connectLowlevel() throws XmlBlasterException {
      if (this.driver == null)
         throw new XmlBlasterException(glob, ErrorCode.RESOURCE_CONFIGURATION_PLUGINFAILED, ME, "Sorry, protocol type='" + super.address.getType() + "' is not supported");
      this.driver.connectLowlevel((Address)super.address);
      if (super.address.getPingInterval() > 0) {
         //spanPingTimer(1, true); // Could deadlock as it uses complete dispatch framework with its synchronized?
         this.driver.ping("<qos><state info='"+Constants.INFO_INITIAL+"'/></qos>")// Try a low level ping
      }
      if (log.isLoggable(Level.FINE)) log.fine("Connected low level to " + super.address.toString());
   }

   /**
    * Send the messages to xmlBlaster.
    * @param msgArr The messages to send.
    *  msgArr[i].getReturnVal() will contain the returned QoS object or null for oneway operations
    * @param isAsyncMode true if coming from queue
    */
   public void doSend(MsgQueueEntry[] msgArr_, boolean isAsyncMode) throws XmlBlasterException {
      if (msgArr_.length < 1) {
         return;
      }

      boolean onlyPublish = true;
      boolean onlyPublishOneway = true;
      for (int ii=0; ii<msgArr_.length; ii++) {
         if (MethodName.PUBLISH_ONEWAY != msgArr_[ii].getMethodName())
            onlyPublishOneway = false;
         if (MethodName.PUBLISH != msgArr_[ii].getMethodName())
            onlyPublish = false;
      }
      if (onlyPublishOneway || onlyPublish) {
         publish(msgArr_);
         return;
      }
     
      for (int ii=0; ii<msgArr_.length; ii++) {
         try {
            if (MethodName.PUBLISH_ONEWAY == msgArr_[ii].getMethodName()) {
               MsgQueueEntry[] tmp = new MsgQueueEntry[] { msgArr_[ii] };
               publish(tmp);
            }
            else if (MethodName.PUBLISH == msgArr_[ii].getMethodName()) {
               MsgQueueEntry[] tmp = new MsgQueueEntry[] { msgArr_[ii] };
               publish(tmp);
            }
            else if (MethodName.GET == msgArr_[ii].getMethodName()) {
               get(msgArr_[ii]);
            }
            else if (MethodName.SUBSCRIBE == msgArr_[ii].getMethodName()) {
               subscribe(msgArr_[ii]);
            }
            else if (MethodName.UNSUBSCRIBE == msgArr_[ii].getMethodName()) {
               unSubscribe(msgArr_[ii]);
            }
            else if (MethodName.ERASE == msgArr_[ii].getMethodName()) {
               erase(msgArr_[ii]);
            }
            else if (MethodName.CONNECT == msgArr_[ii].getMethodName()) {
               if (isAsyncMode && isAlive() && this.driver.isLoggedIn()) {
                  return; // Coming from queue but we are alive already
               }
               connect(msgArr_[ii]);
               this.connectEntry = msgArr_[ii]; // remember it
            }
            else if (MethodName.DISCONNECT == msgArr_[ii].getMethodName()) {
               this.connectEntry = null;
               disconnect(msgArr_[ii]);
            }
            else {
               throw new XmlBlasterException(glob, ErrorCode.INTERNAL_NOTIMPLEMENTED, ME, "Message type '" + msgArr_[ii].getEmbeddedType() + "' is not implemented");
            }
         }
         catch (XmlBlasterException e) {
            if (this.connectEntry != null && e.isErrorCode(ErrorCode.USER_SECURITY_AUTHENTICATION_ACCESSDENIED)) {
               // Happens if the client was killed in the server by an admin task
               // and has tried to reconnect with the old sessionId
               log.warning("Server changed sessionId, trying reconnect now: " + e.toString());
               //reconnect();   // loops?!
               connect(this.connectEntry);
               connectionsHandler.getDispatchManager().postSendNotification(this.connectEntry);
               if (log.isLoggable(Level.FINE)) log.fine("Server changed sessionId to " + this.connectReturnQos.getServerInstanceId());
               ii--;
            }
            else {
               throw e;
            }
         }
      }
   }
  
   private void setCheckpointContext(ConnectReturnQos qr) {
      if (qr == null) {
         this.checkPointContext = null;
         return;
      }
      this.checkPointContext = new String[] {"sessionName", qr.getSessionName().getAbsoluteName()};
   }

   private void publish(MsgQueueEntry[] msgArr_) throws XmlBlasterException {
     
      I_Checkpoint cp = glob.getCheckpointPlugin();

      // Convert to PublishEntry
      MsgUnit[] msgArr = new MsgUnit[msgArr_.length];
      for (int i=0; i<msgArr.length; i++) {
         MsgQueuePublishEntry publishEntry = (MsgQueuePublishEntry)msgArr_[i];
         msgArr[i] = publishEntry.getMsgUnit();
      }

      MsgUnitRaw[] msgUnitRawArr = new MsgUnitRaw[msgArr.length];
      // We export/encrypt the message (call the interceptor)
      if (securityInterceptor != null) {
         for (int i=0; i<msgArr.length; i++) {
            CryptDataHolder dataHolder = new CryptDataHolder(MethodName.PUBLISH, msgArr[i].getMsgUnitRaw());
            msgUnitRawArr[i] = securityInterceptor.exportMessage(dataHolder);
         }
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted " + msgArr.length + " publish messages.");
      }
      else {
         log.warning("No session security context, sending " + msgArr.length + " publish messages without encryption");
         for (int i=0; i<msgArr.length; i++) {
            msgUnitRawArr[i] = msgArr[i].getMsgUnitRaw();
         }
      }

      if (MethodName.PUBLISH_ONEWAY == msgArr_[0].getMethodName()) {
         this.driver.publishOneway(msgUnitRawArr);
         connectionsHandler.getDispatchStatistic().incrNumPublish(msgUnitRawArr.length);
         if (log.isLoggable(Level.FINE)) log.fine("Success, sent " + msgArr.length + " oneway publish messages.");
         if (cp != null) {
            for (int i=0; i<msgArr.length; i++) {
               cp.passingBy(I_Checkpoint.CP_CONNECTION_PUBLISH_ACK, msgArr[i],
                     null, this.checkPointContext);
            }
         }
         return;
      }

      if (log.isLoggable(Level.FINE)) log.fine("Before publish " + msgArr.length + " acknowledged messages ...");

      String[] rawReturnVal = this.driver.publishArr(msgUnitRawArr);
      if (rawReturnVal == null) {
         String text = "driver.publishArr len= " + msgUnitRawArr.length + " returned null: " + ((msgUnitRawArr.length>0)?msgUnitRawArr[0].getKey():"");
         throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME, text);
      }
      connectionsHandler.getDispatchStatistic().incrNumPublish(rawReturnVal.length);

      if (log.isLoggable(Level.FINE)) log.fine("Success, sent " + msgArr.length + " acknowledged publish messages, return value #1 is '" + rawReturnVal[0] + "'");

      if (rawReturnVal != null) {
         for (int i=0; i<rawReturnVal.length; i++) {
            if (cp != null) {
               MsgQueuePublishEntry publishEntry = (MsgQueuePublishEntry)msgArr_[i];
               cp.passingBy(I_Checkpoint.CP_CONNECTION_PUBLISH_ACK, publishEntry.getMsgUnit(),
                        null, this.checkPointContext);
            }
           
            if (!msgArr_[i].wantReturnObj())
               continue;

            if (securityInterceptor != null) {
               CryptDataHolder dataHolder = new CryptDataHolder(MethodName.PUBLISH, new MsgUnitRaw(null, (byte[])null, rawReturnVal[i]));
               dataHolder.setReturnValue(true);
               rawReturnVal[i] = securityInterceptor.importMessage(dataHolder).getQos();
            }

            // create return object
            try {
               msgArr_[i].setReturnObj(new PublishReturnQos(glob, rawReturnVal[i]));
            }
            catch (Throwable e) {
               log.warning("Can't parse publish returned value '" + rawReturnVal[i] + "', setting to default: " + e.toString());
               //e.printStackTrace();
               msgArr_[i].setReturnObj(new PublishReturnQos(glob, "<qos/>"));
            }
         }
         if (log.isLoggable(Level.FINE)) log.fine("Imported/decrypted " + rawReturnVal.length + " publish message return values.");
      }
   }

   /**
    * Encrypt and send a subscribe request, decrypt the returned data
    */
   private void subscribe(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueSubscribeEntry subscribeEntry = (MsgQueueSubscribeEntry)entry;

      String key = subscribeEntry.getSubscribeKeyData().toXml();
      String qos = subscribeEntry.getSubscribeQosData().toXml();
      if (securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.SUBSCRIBE, new MsgUnitRaw(key, (byte[])null, qos));
         MsgUnitRaw msgUnitRaw = securityInterceptor.exportMessage(dataHolder);
         key = msgUnitRaw.getKey();
         qos = msgUnitRaw.getQos();
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted subscribe request.");
      }
      else {
         log.warning("No session security context, subscribe request is not encrypted");
      }

      String rawReturnVal = this.driver.subscribe(key, qos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumSubscribe(1);
     
      if (subscribeEntry.wantReturnObj()) {
         if (securityInterceptor != null) { // decrypt return value ...
            CryptDataHolder dataHolder = new CryptDataHolder(MethodName.SUBSCRIBE, new MsgUnitRaw(null, (byte[])null, rawReturnVal));
            dataHolder.setReturnValue(true);
            rawReturnVal = securityInterceptor.importMessage(dataHolder).getQos();
         }
         try {
            subscribeEntry.setReturnObj(new SubscribeReturnQos(glob, rawReturnVal));
         }
         catch (Throwable e) {
            log.warning("Can't parse returned subscribe value '" + rawReturnVal + "', setting to default: " + e.toString());
            subscribeEntry.setReturnObj(new SubscribeReturnQos(glob, "<qos/>"));
         }
      }
   }

   /**
    * Encrypt and send a unSubscribe request, decrypt the returned data
    */
   private void unSubscribe(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueUnSubscribeEntry unSubscribeEntry = (MsgQueueUnSubscribeEntry)entry;

      String key = unSubscribeEntry.getUnSubscribeKey().toXml();
      String qos = unSubscribeEntry.getUnSubscribeQos().toXml();
      if (securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.UNSUBSCRIBE, new MsgUnitRaw(key, (byte[])null, qos));
         MsgUnitRaw msgUnitRaw = securityInterceptor.exportMessage(dataHolder);
         key = msgUnitRaw.getKey();
         qos = msgUnitRaw.getQos();
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted unSubscribe request.");
      }
      else {
         log.warning("No session security context, unSubscribe request is not encrypted");
      }

      String[] rawReturnValArr = this.driver.unSubscribe(key, qos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumUnSubscribe(1);
     
      if (unSubscribeEntry.wantReturnObj()) {
         UnSubscribeReturnQos[] retQosArr = new UnSubscribeReturnQos[rawReturnValArr.length];
         for (int ii=0; ii<rawReturnValArr.length; ii++) {
            if (securityInterceptor != null) { // decrypt return value ...
               CryptDataHolder dataHolder = new CryptDataHolder(MethodName.UNSUBSCRIBE, new MsgUnitRaw(null, (byte[])null, rawReturnValArr[ii]));
               dataHolder.setReturnValue(true);
               String xmlQos = securityInterceptor.importMessage(dataHolder).getQos();
               retQosArr[ii] = new UnSubscribeReturnQos(glob, xmlQos);
            }
         }

         try {
            unSubscribeEntry.setReturnObj(retQosArr);
         }
         catch (Throwable e) {
            log.warning("Can't parse returned unSubscribe value setting to default: " + e.toString());
            for (int ii=0; ii<rawReturnValArr.length; ii++) {
               retQosArr[ii] = new UnSubscribeReturnQos(glob, "<qos/>");
            }
            unSubscribeEntry.setReturnObj(retQosArr);
         }
      }
   }

   /**
    * Encrypt and send a synchronous get request, decrypt the returned data
    */
   private void get(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueGetEntry getEntry = (MsgQueueGetEntry)entry;

      String key = getEntry.getGetKey().toXml();
      String qos = getEntry.getGetQos().toXml();
      if (this.securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.GET, new MsgUnitRaw(key, (byte[])null, qos));
         MsgUnitRaw msgUnitRaw = securityInterceptor.exportMessage(dataHolder);
         key = msgUnitRaw.getKey();
         qos = msgUnitRaw.getQos();
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted get request.");
      }
      else {
         log.warning("No session security context, get request is not encrypted");
      }

      MsgUnitRaw[] rawReturnValArr = this.driver.get(key, qos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumGet(1);
     
      MsgUnit[] msgUnitArr = new MsgUnit[rawReturnValArr.length];
      if (getEntry.wantReturnObj()) {
         for (int ii=0; ii<rawReturnValArr.length; ii++) {
            if (this.securityInterceptor != null) { // decrypt return value ...
               CryptDataHolder dataHolder = new CryptDataHolder(MethodName.GET, rawReturnValArr[ii]);
               dataHolder.setReturnValue(true);
               rawReturnValArr[ii] = securityInterceptor.importMessage(dataHolder);
            }
            // NOTE: We use PUBLISH here instead of GET_RETURN to have the whole MsgUnit stored
            msgUnitArr[ii] = new MsgUnit(glob, rawReturnValArr[ii], MethodName.PUBLISH);
         }

         getEntry.setReturnObj(msgUnitArr);
      }
   }

   /**
    * Encrypt and send a erase request, decrypt the returned data
    */
   private void erase(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueEraseEntry eraseEntry = (MsgQueueEraseEntry)entry;

      String key = eraseEntry.getEraseKey().toXml();
      String qos = eraseEntry.getEraseQos().toXml();
      if (securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.ERASE, new MsgUnitRaw(key, (byte[])null, qos));
         MsgUnitRaw msgUnitRaw = securityInterceptor.exportMessage(dataHolder);
         key = msgUnitRaw.getKey();
         qos = msgUnitRaw.getQos();
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted erase request.");
      }
      else {
         log.warning("No session security context, erase request is not encrypted");
      }

      String[] rawReturnValArr = this.driver.erase(key, qos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumErase(1);
     
      if (eraseEntry.wantReturnObj()) {
         EraseReturnQos[] retQosArr = new EraseReturnQos[rawReturnValArr.length];
         for (int ii=0; ii<rawReturnValArr.length; ii++) {
            if (securityInterceptor != null) { // decrypt return value ...
               CryptDataHolder dataHolder = new CryptDataHolder(MethodName.ERASE, new MsgUnitRaw(null, (byte[])null, rawReturnValArr[ii]));
               dataHolder.setReturnValue(true);
               String xmlQos = securityInterceptor.importMessage(dataHolder).getQos();
               retQosArr[ii] = new EraseReturnQos(glob, xmlQos);
            }
         }

         try {
            eraseEntry.setReturnObj(retQosArr);
         }
         catch (Throwable e) {
            log.warning("Can't parse returned erase value setting to default: " + e.toString());
            for (int ii=0; ii<rawReturnValArr.length; ii++) {
               retQosArr[ii] = new EraseReturnQos(glob, "<qos/>");
            }
            eraseEntry.setReturnObj(retQosArr);
         }
      }
   }

   /**
    * Remember the cqd in this.connectQosData and return the encrypted string.
    */  
   private String getEncryptedConnectQos(ConnectQosData cqd) throws XmlBlasterException {
      if (cqd == null) {
         return null;
      }
      cqd.addClientProperty(Constants.CLIENTPROPERTY_UTC, IsoDateParser.getCurrentUTCTimestamp());
      this.connectQosData = cqd;
      if (this.securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
          if (log.isLoggable(Level.FINE)) log.fine("TODO: Crypting msg with exportMessage() is not supported for connect() as the server currently can't handle encrypted ConnectQos (for SOCKET see HandleClient.java:234)");
          CryptDataHolder dataHolder = new CryptDataHolder(MethodName.CONNECT, new MsgUnitRaw(null, (byte[])null, cqd.toXml()));
          String encryptedConnectQos = this.securityInterceptor.exportMessage(dataHolder).getQos();
          if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted connect request.");
          return encryptedConnectQos;
      }
      else {
          log.warning("No session security context, connect request is not encrypted");
          return cqd.toXml();
      }
   }

   /**
    * Encrypt and send a connect request, decrypt the returned data
    */
   private void connect(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueConnectEntry connectEntry = (MsgQueueConnectEntry)entry;
      this.sessionName = connectEntry.getConnectQosData().getSessionName();

      String encryptedConnectQos = getEncryptedConnectQos(connectEntry.getConnectQosData());

      // TODO: pass connectEntry.getConnectQosData().getSender().getLoginName(); as this is used by SOCKET:requestId
      String rawReturnVal = this.driver.connect(encryptedConnectQos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumConnect(1);
     
      if (securityInterceptor != null) { // decrypt return value ...
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.CONNECT, new MsgUnitRaw(null, (byte[])null, rawReturnVal));
         dataHolder.setReturnValue(true);
         rawReturnVal = securityInterceptor.importMessage(dataHolder).getQos();
      }

      try {
         this.connectReturnQos = new ConnectReturnQos(glob, rawReturnVal);
         setCheckpointContext(this.connectReturnQos);
      }
      catch (XmlBlasterException e) {
         log.severe("Can't parse returned connect QoS value '" + rawReturnVal + "': " + e.getMessage());
         throw e;
      }

      if (!connectEntry.getConnectQosData().getSessionName().isSession()) {
         // We need to remember the server side assigned public session id for reconnect polling
         // If do we should probably take a clone:
         //ConnectQos connectQos = new ConnectQos(this.glob, this.connectReturnQos.getData());
         ConnectQosData connectQos = connectEntry.getConnectQosData();
         connectQos.setSessionName(this.connectReturnQos.getSessionName());
         this.sessionName = this.connectReturnQos.getSessionName();
         connectQos.getSessionQos().setSecretSessionId(this.connectReturnQos.getSecretSessionId());
         this.connectQosData = connectQos;
      }

      if (connectEntry.wantReturnObj()) {
         connectEntry.setReturnObj(this.connectReturnQos);
      }
      this.driver.setConnectReturnQos(this.connectReturnQos);
   }

   /**
    * Encrypt and send a disconnect request, decrypt the returned data
    */
   private void disconnect(MsgQueueEntry entry) throws XmlBlasterException {
      MsgQueueDisconnectEntry disconnectEntry = (MsgQueueDisconnectEntry)entry;
      String qos = disconnectEntry.getDisconnectQos().toXml();
      if (securityInterceptor != null) {  // We export/encrypt the message (call the interceptor)
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.DISCONNECT, new MsgUnitRaw(null, (byte[])null, qos));
         qos = securityInterceptor.exportMessage(dataHolder).getQos();
         if (log.isLoggable(Level.FINE)) log.fine("Exported/encrypted disconnect request.");
      }
      else {
         log.warning("No session security context, disconnect request is not encrypted");
      }

      //returns void
      this.driver.disconnect(qos); // Invoke remote server
   }

   /**
    * @see org.xmlBlaster.util.dispatch.DispatchConnection#doPing(String)
    */
   public final String doPing(String data) throws XmlBlasterException {
      String ret = driver.ping(data);
      return (ret==null) ? "" : ret;
   }

   /**
    * Nothing to do here
    */
   public final void resetConnection() {
      if (log.isLoggable(Level.FINE)) log.fine("resetConnection(): Initializing driver for polling");
      this.connectReturnQos = null;
      this.driver.resetConnection();
   }

   /**
    * On reconnect polling try to establish the connection.
    */
   protected final void reconnect() throws XmlBlasterException {
      if (this.driver == null) return;
      if (log.isLoggable(Level.FINER)) log.finer("Entering reconnect(" + this.driver.getProtocol() + ")");

      if (this.connectReturnQos != null) {
         // needed to avoid failure
         this.connectionsHandler.getDispatchStatistic().clearCurrentReads();
         this.connectionsHandler.getDispatchStatistic().clearCurrentWrites();
         super.ping("", false);
         return;
      }

      if (this.connectQosData == null) {
         // We never had connected on application layer, so try low level layer only
         this.driver.connectLowlevel((Address)super.address);
         return;
      }

      String encryptedConnectQos = getEncryptedConnectQos(this.connectQosData);
      // low level connect (e.g. on TCP/IP layer) and remote invoke method connect()
      String rawReturnVal = this.driver.connect(encryptedConnectQos); // Invoke remote server

      connectionsHandler.getDispatchStatistic().incrNumConnect(1);
     
      if (securityInterceptor != null) { // decrypt return value ...
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.CONNECT, new MsgUnitRaw(null, (byte[])null, rawReturnVal));
         dataHolder.setReturnValue(true);
         rawReturnVal = securityInterceptor.importMessage(dataHolder).getQos();
      }

      this.connectReturnQos = null;
      try {
         this.connectReturnQos = new ConnectReturnQos(glob, rawReturnVal);
         setCheckpointContext(this.connectReturnQos);
         if (this.connectEntry != null) {
            if (this.connectEntry.wantReturnObj()) {
               this.connectEntry.setReturnObj(this.connectReturnQos);
            }
            connectionsHandler.getDispatchManager().postSendNotification(this.connectEntry);
         }
      }
      catch (XmlBlasterException e) {
         log.severe("reconnect(): Can't parse returned connect QoS value '" + rawReturnVal + "': " + e.getMessage());
         throw e;
      }
      this.driver.setConnectReturnQos(this.connectReturnQos);
   }

   /**
    * Stop all callback drivers of this client.
    */
   public final void shutdown() throws XmlBlasterException {
      super.shutdown();
      if (driver != null) {
         driver.shutdown();
      }
   }

   /**
    * Dump state of this object into a XML ASCII string.
    * <br>
    * @param extraOffset indenting of tags for nice output
    * @return internal state as an XML ASCII string
    */
   public final String toXml(String extraOffset) {
      StringBuffer sb = new StringBuffer(256);
      if (extraOffset == null) extraOffset = "";
      String offset = Constants.OFFSET + extraOffset;

      sb.append(offset + "<ClientDispatchConnection>");
      super.address.toXml(" " + offset);
      if (driver == null)
         sb.append(offset).append(" <noProtocolDriver />");
      else
         sb.append(offset).append(" <address type='" + driver.getProtocol() + "' state='" + getState() + "'/>");
      sb.append(offset).append("</ClientDispatchConnection>");

      return sb.toString();
   }
  
   public I_ProgressListener registerProgressListener(I_ProgressListener listener) {
      if (this.driver == null) return null;
      return this.driver.registerProgressListener(listener);
   }

   protected boolean forcePingFailure() {
      return true;
   }
  
}
TOP

Related Classes of org.xmlBlaster.client.dispatch.ClientDispatchConnection

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.