Package org.xmlBlaster.protocol.socket

Source Code of org.xmlBlaster.protocol.socket.CallbackSocketDriver

/*------------------------------------------------------------------------------
Name:      CallbackSocketDriver.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/
package org.xmlBlaster.protocol.socket;

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

import org.xmlBlaster.protocol.I_CallbackDriver;
import org.xmlBlaster.util.Global;
import org.xmlBlaster.util.I_Timeout;
import org.xmlBlaster.util.MsgUnitRaw;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.plugin.PluginInfo;
import org.xmlBlaster.util.protocol.socket.SocketExecutor;
import org.xmlBlaster.util.qos.address.CallbackAddress;
import org.xmlBlaster.util.xbformat.I_ProgressListener;
import org.xmlBlaster.util.xbformat.XbfParser;


/**
* One instance of this for each client to send him callback.
* <p />
* This is sort of a dummy needed by the plugin framework which
* assumed for CORBA/RMI/XMLRPC a separate callback connection
* @author xmlBlaster@marcelruff.info
*/
public class CallbackSocketDriver implements I_CallbackDriver /* which extends I_Plugin */
{
   private String ME = "CallbackSocketDriver";
   private Global glob = null;
   private static Logger log = Logger.getLogger(CallbackSocketDriver.class.getName());
   private String loginName;
   private SocketExecutor handler;
   private CallbackAddress callbackAddress;
   //private boolean isFirstPing_hack = true;
   private PluginInfo pluginInfo; // remains null as we are loaded dynamically
   private String msgInfoParserClassName;
   private boolean useUdpForOneway;

   /**
    * Should not be instantiated by plugin loader.
    * A dummy could be created temporary by reflection?
    */
   public CallbackSocketDriver() {
      //log.severe("Empty Ctor not expected");
      //(new Exception("")).printStackTrace();
   }

   /**
    * This constructor is called when
    * <br />
    * 1.on server side when the client arrives in HandleClient
    * <br />
    * 2.the callback shall be tunneled through by
    * the SAME SOCKET connection which the client already has established.
    */
   public CallbackSocketDriver(String loginName, SocketExecutor handler) {
      this.loginName = loginName;
      this.ME += "-" + this.loginName;
      this.handler = handler;
      this.useUdpForOneway = handler.useUdpForOneway();
   }

   /**
    * This constructor is called when the callback shall be delivered by
    * a separate SOCKET connection which we open here (in initialize())
    */
   public CallbackSocketDriver(String loginName /*, CallbackAddress callbackAddress*/) {
      this.loginName = loginName;
      this.ME += "-" + this.loginName;
      //this.callbackAddress = callbackAddress;
   }

   public String getName() {
      return Global.getStrippedString(this.ME);
   }

   /**
    * Access the xmlBlaster internal name of the protocol driver.
    * @return "SOCKET"
    */
   public String getProtocolId() {
      return (this.pluginInfo == null) ? "SOCKET" : this.pluginInfo.getType();
   }

   /** Enforced by I_Plugin */
   public String getType() {
      return getProtocolId();
   }

   /** Enforced by I_Plugin */
   public String getVersion() {
      return (this.pluginInfo == null) ? "1.0" : this.pluginInfo.getVersion();
   }

   /**
    * This method is called by the PluginManager (enforced by I_Plugin).
    * @see org.xmlBlaster.util.plugin.I_Plugin#init(org.xmlBlaster.util.Global,org.xmlBlaster.util.plugin.PluginInfo)
    */
   public void init(org.xmlBlaster.util.Global glob, PluginInfo pluginInfo) {
      if (log == null) {
         this.glob = glob;

      }
      // This can happen when on xmlBlaster restart a session is recovered from persistency
      // and the client has not yet connected (so we can't reuse its socket for callbacks).
      // In such a case this callback driver is loaded as a dummy.
      log.fine("init(PluginInfo) call not is expected, we are loaded dynamically if configured by ConnectQos");
      this.pluginInfo = pluginInfo;
   }

   /**
    * Get the address how to access this driver.
    * @return "server.mars.univers:6701"
    */
   public String getRawAddress() {
      return this.callbackAddress.getRawAddress();
   }

   public void init(Global glob, CallbackAddress callbackAddress)
      throws XmlBlasterException {
      this.glob = glob;

      this.ME = "CallbackSocketDriver" + this.glob.getLogPrefixDashed();
      if (log.isLoggable(Level.FINER)) log.finer("init()");
      this.callbackAddress = callbackAddress;
     
      //if (this.pluginInfo == null) {
         // Use configuration parameters from xmlBlaster.properties (to be able to change parserClass)
         // even that we are instantiated directly (socket callback tunnel) and not by plugin manager
         //CbProtocolPlugin[socket_script][1.0]=org.xmlBlaster.protocol.socket.CallbackSocketDriver,\
         //compress/type=,\
         //isNullTerminated=true,\
         //parserClass=org.xmlBlaster.util.xbformat.XmlScriptParser
         try {
            this.msgInfoParserClassName = null; // reset
            this.pluginInfo = ((org.xmlBlaster.engine.ServerScope)glob).getCbProtocolManager().getPluginInfo(this.callbackAddress.getType(), this.callbackAddress.getVersion());
            if (this.pluginInfo != null) {
               this.callbackAddress.setPluginInfoParameters(this.pluginInfo.getParameters());
            }
         }
         catch (XmlBlasterException e) {
            // Don't log if no configuration is found
            if (e.isErrorCode(ErrorCode.RESOURCE_CONFIGURATION))
               log.fine("No socket protocol type '" + this.callbackAddress.getType() + "' configuration loaded: " + e.toString());
            else
               log.warning("No socket protocol type '" + this.callbackAddress.getType() + "' configuration loaded: " + e.toString());
         }
         catch (Throwable e) {
            e.printStackTrace();
            log.warning("No socket protocol type '" + this.callbackAddress.getType() + "' configuration loaded: " + e.toString());
         }
      //}
        
      // Wrong code to be removed
      Object obj = this.callbackAddress.getCallbackDriver();
      if (obj != null && obj instanceof SocketExecutor) { //SocketCallbackImpl
         Thread.dumpStack();
         this.handler = (SocketExecutor)obj;
      }
   }

   /**
    * This sends the update to the client.
    * @exception e.id="CallbackFailed", should be caught and handled appropriate
    */
   public final String[] sendUpdate(MsgUnitRaw[] msgArr) throws XmlBlasterException {
      if (this.handler == null)
         throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME,
                  "SOCKET sendUpdate failed, the handle is null");
      return this.handler.sendUpdate(callbackAddress.getSecretSessionId(), msgArr,
             SocketExecutor.WAIT_ON_RESPONSE, this.useUdpForOneway, getPluginInfo());
   }

   /**
    * The oneway variant, without return value.
    * @exception XmlBlasterException Is never from the client (oneway).
    */
   public void sendUpdateOneway(MsgUnitRaw[] msgArr) throws XmlBlasterException {
      if (this.handler == null)
         throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME,
                  "SOCKET sendUpdateOneway failed");
      this.handler.sendUpdate(callbackAddress.getSecretSessionId(), msgArr,
            SocketExecutor.ONEWAY, this.useUdpForOneway, getPluginInfo());
   }

   /**
    * Ping to check if callback server is alive.
    * This ping checks the availability on the application level.
    * @param qos Currently an empty string ""
    * @return    Currently an empty string ""
    * @exception XmlBlasterException If client not reachable
    */
   public final String ping(String qos) throws XmlBlasterException {
      // "<qos><state info='INITIAL'/></qos>"
      // Send from CbDispatchConnection.java on connect
      if (qos != null && qos.indexOf(Constants.INFO_INITIAL) != -1) {
         if (log.isLoggable(Level.FINE)) log.fine("Socket callback ping is suppressed as doing it before connect() may" +
         " block the clients connect() if the callback is not functional");
         return Constants.RET_OK;
      }
      /*
      if (this.isFirstPing_hack) {
         // Ingore first ping (which is triggered by dispatch framework after plugin creation
         // It leads to a deadlock since we are working on a connec() and should first return the ConnectReturnQos
         // See CbDispatchConnection.java this.cbDriver.ping("");
         this.isFirstPing_hack = false;
         return "";
      }
      */
     
      SocketExecutor se = this.handler;
      if (se == null)
         throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME,
                  "SOCKET callback ping failed, handler is null");
      try {
         return se.ping(qos);
      } catch (Throwable e) {
         throw new XmlBlasterException(glob, ErrorCode.COMMUNICATION_NOCONNECTION, ME,
                     "CallbackSocketDriver " + getType() + " callback ping failed", e);
      }
   }

   public I_ProgressListener registerProgressListener(I_ProgressListener listener) {
      if (this.handler == null) return null;
      return this.handler.registerProgressListener(listener);
   }

   final I_ProgressListener getProgressListener() {
      if (this.handler == null) return null;
      return this.handler.getProgressListener();
   }

   public void shutdown() {
      if (log != null) {
         if (log.isLoggable(Level.FINER)) log.finer("shutdown()");
      }
      final SocketExecutor se = this.handler;
      if (se != null) {
         // The core can not do it, it does not know the HandleClient instance
         // it would be possible to pass the HandleClient with AddressServer to
         // the core but this needs to be discussed
         //this.handler.shutdown();
        
         // Give a Authenticate.connect exception to be delivered to the client
         // or the client some chance to close the socket itself after disconnect
         long delay = 5000; // 5 sec
         glob.getBurstModeTimer().addTimeoutListener(new I_Timeout() {
               public void timeout(Object userData) {
                  se.shutdown();
                  //handler = null;
               }
            }, delay, null);
      }
   }
  
   /**
    * @return true if the plugin is still alive, false otherwise
    */
   public boolean isAlive() {
      return this.handler != null && !this.handler.isShutdown();
   }

   /**
    * @return the pluginInfo:
    * Always null as we are loaded dynamically!
    */
   public PluginInfo getPluginInfo() {
      return this.pluginInfo;
   }

   /**
    * @return the callbackAddress
    */
   public CallbackAddress getCallbackAddress() {
      return this.callbackAddress;
   }
  
   /**
    * Which parser to use.
    * The SOCKET protocol uses as a default setting the XbfParser
    * @return The class name of the parser, "org.xmlBlaster.util.xbformat.XbfParser"
    */
   public String getMsgInfoParserClassName() {
      if (this.msgInfoParserClassName == null) {
         synchronized (this) {
            if (this.msgInfoParserClassName == null && this.callbackAddress != null) {
               this.msgInfoParserClassName = this.callbackAddress.getEnv("parserClass", XbfParser.class.getName()).getValue();
            }
         }
      }
      return this.msgInfoParserClassName; // "org.xmlBlaster.util.xbformat.XbfParser"
   }
  
   public SocketExecutor getHandler() {
      return handler;
   }
}
TOP

Related Classes of org.xmlBlaster.protocol.socket.CallbackSocketDriver

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.