Package org.xmlBlaster.client.protocol

Source Code of org.xmlBlaster.client.protocol.AbstractCallbackExtended

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

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

import org.xmlBlaster.client.key.UpdateKey;
import org.xmlBlaster.client.qos.UpdateQos;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.def.MethodName;
import org.xmlBlaster.util.dispatch.DispatchStatistic;
import org.xmlBlaster.util.Global;
import org.xmlBlaster.authentication.plugins.CryptDataHolder;
import org.xmlBlaster.authentication.plugins.I_ClientPlugin;
import org.xmlBlaster.util.MsgUnitRaw;


/**
* This is a little abstract helper class which extends the I_CallbackExtended
* interface to become suited for protocols like xml-rpc. Note that you need to
* extend this class because one of the update methods is abstract.
* <p>
*
* @version $Revision: 1.16 $
* @author <a href="mailto:michele@laghi.eu">Michele Laghi</a>
* @author <a href="mailto:xmlBlaster@marcelruff.info">Marcel Ruff</a>.
*/
public abstract class AbstractCallbackExtended implements I_CallbackExtended
{
   private String ME = "AbstractCallbackExtended";
   protected final Global glob;
   private static Logger log = Logger.getLogger(AbstractCallbackExtended.class.getName());
   protected boolean updateBulkAck;
  
   /**
    * @param glob If null we use Global.instance()
    */
   public AbstractCallbackExtended(Global glob) {
      this.glob = (glob==null) ? Global.instance() : glob;

   }

   public abstract I_ClientPlugin getSecurityPlugin();
  
   /**
    * Access the statistic holder.
    * Implementing classes should provide a valid statistic handle.
    * @return Can be null
    */
   public DispatchStatistic getDispatchStatistic() {
          return null;
   }

   /**
    * It parses the string literals passed in the argument list and calls
    * subsequently the update method with the signature defined in I_Callback.
    * <p>
    * This method is invoked by certain protocols only. Others might directly
    * invoke the update method with the other signature.
    *
    * @param cbSessionId The session ID specified by the client which registered the callback
    * @param updateKeyLiteral The arrived key (as an xml-string)
    * @param content   The arrived message content
    * @param updateQosLiteral  Quality of Service of the MsgUnitRaw
    *                      (as an xml-string)
    * @see I_CallbackExtended
    */
   public String update(String cbSessionId, String updateKeyLiteral, byte[] content,
                      String updateQosLiteral) throws XmlBlasterException
   {
      // import (decrypt) message
      I_ClientPlugin secPlgn = getSecurityPlugin();
      if (secPlgn != null) {
         MsgUnitRaw in = new MsgUnitRaw(updateKeyLiteral, content, updateQosLiteral);
         CryptDataHolder dataHolder = new CryptDataHolder(MethodName.UPDATE, in, null);
         MsgUnitRaw msg = secPlgn.importMessage(dataHolder);
         updateKeyLiteral = msg.getKey();
         content = msg.getContent();
         updateQosLiteral = msg.getQos();
      }

      // parse XML key and QoS
      UpdateKey updateKey = null;
      UpdateQos updateQos = null;
      try {
         updateKey = new UpdateKey(glob, updateKeyLiteral);
         //updateKey.init(updateKeyLiteral); // does the parsing
         updateQos = new UpdateQos(glob, updateQosLiteral); // does the parsing
      }
      catch (XmlBlasterException e) {
         log.severe("Parsing error: " + e.toString());
         throw new XmlBlasterException(glob, ErrorCode.USER_UPDATE_ILLEGALARGUMENT, ME+".update", "Parsing error", e);
      }

      // invoke client code
      try {
         // Now we know all about the received message, dump it or do some checks
         /*
         if (log.isLoggable(Level.FINEST)) log.dump(ME+".UpdateKey", "\n" + updateKey.toXml());
         if (log.isLoggable(Level.FINEST)) log.dump(ME+".content", "\n" + new String(content));
         if (log.isLoggable(Level.FINEST)) log.dump(ME+".UpdateQos", "\n" + updateQos.toXml());
         */
         if (log.isLoggable(Level.FINE)) log.fine("Received message [" + updateKey.getOid() + "] from publisher " + updateQos.getSender());

         String ret = update(cbSessionId, updateKey, content, updateQos);

         DispatchStatistic statistic = getDispatchStatistic();
         if (statistic != null) statistic.incrNumUpdate(1);
        
         // export (encrypt) return value
         if (secPlgn != null) {
            MsgUnitRaw msg = new MsgUnitRaw(null, (byte[])null, ret);
            CryptDataHolder dataHolder = new CryptDataHolder(MethodName.UPDATE, msg, null);
            dataHolder.setReturnValue(true);
            ret = secPlgn.exportMessage(dataHolder).getQos();
         }

         return ret;
      }
      catch (XmlBlasterException e) {
         throw e;
      }
      catch (Throwable e) {
         e.printStackTrace();
         log.warning("Error in client user code of update("+
                      ((updateKey!=null)?updateKey.getOid():"")+
                      ((updateQos!=null)?", "+updateQos.getRcvTime():"")+
                      "): " + e.toString());
         throw new XmlBlasterException(glob, ErrorCode.USER_UPDATE_INTERNALERROR, ME+".update", "Error in client code, please check your clients update() implementation.", e);
      }
   }

   /**
    * The oneway variant without a return value or exception
    * <p />
    * We match it to the blocking variant. Implement this in your code on demand.
    */
   public void updateOneway(String cbSessionId, String updateKeyLiteral, byte[] content, String updateQosLiteral)
   {
      try {
         I_ClientPlugin secPlgn = getSecurityPlugin();
         if (secPlgn != null) {
            MsgUnitRaw in = new MsgUnitRaw(updateKeyLiteral, content, updateQosLiteral);
            CryptDataHolder dataHolder = new CryptDataHolder(MethodName.UPDATE_ONEWAY, in, null);
            MsgUnitRaw msg = secPlgn.importMessage(dataHolder);

            updateKeyLiteral = msg.getKey();
            content = msg.getContent();
            updateQosLiteral = msg.getQos();
         }

         UpdateKey updateKey = new UpdateKey(glob, updateKeyLiteral);
         UpdateQos updateQos = new UpdateQos(glob, updateQosLiteral);
         if (log.isLoggable(Level.FINE)) log.fine("Received message [" + updateKey.getOid() + "] from publisher " + updateQos.getSender());

         update(cbSessionId, updateKey, content, updateQos);

         DispatchStatistic statistic = getDispatchStatistic();
         if (statistic != null) statistic.incrNumUpdateOneway(1);
      }
      catch (Throwable e) {
         log.severe("Caught exception, can't deliver it to xmlBlaster server as we are in oneway mode: " + e.toString());
      }
   }

   /**
    * This is the callback method invoked natively
    * informing the client in an asynchronous mode about new messages.
    * <p />
    * It implements the interface I_CallbackRaw.
    * <p />
    * It nicely converts the raw MsgUnitRaw with raw Strings and arrays
    * in corresponding objects and calls for every received message
    * the I_Callback.update(), which you need to implement in your code.
    *
    * @param msgUnitArr Contains MsgUnitRaw structs (your message) in native form
    */
   public String[] update(String cbSessionId, MsgUnitRaw [] msgUnitArr) throws XmlBlasterException
   {
      if (msgUnitArr == null) {
         log.warning("Entering update() with null array.");
         return new String[0];
      }
      if (msgUnitArr.length == 0) {
         log.warning("Entering update() with 0 messages.");
         return new String[0];
      }
      if (log.isLoggable(Level.FINER)) log.finer("Receiving update of " + msgUnitArr.length + " messages ...");

      String[] retArr = new String[msgUnitArr.length];
      for (int ii=0; ii<msgUnitArr.length; ii++) {
         MsgUnitRaw msgUnit = msgUnitArr[ii];
         retArr[ii] = update(cbSessionId, msgUnit.getKey(), msgUnit.getContent(), msgUnit.getQos());
      }
      if (this.updateBulkAck && retArr.length > 1) {
         for (int i=0; i < retArr.length; i++) {
            if (!Constants.RET_OK.equals(retArr[i]) && !"OK".equals(retArr[i]))
               return new String[] { retArr[i] };
            return new String[] { retArr[0]};
         }
      }
      return retArr;
   }

   /**
    * The oneway variant without a return value or exception
    */
   public void updateOneway(String cbSessionId, org.xmlBlaster.util.MsgUnitRaw[] msgUnitArr)
   {
      if (msgUnitArr == null) {
         log.warning("Entering updateOneway() with null array.");
         return;
      }
      if (msgUnitArr.length == 0) {
         log.warning("Entering updateOneway() with 0 messages.");
         return;
      }
      if (log.isLoggable(Level.FINER)) log.finer("Receiving updateOneway of " + msgUnitArr.length + " messages ...");

      for (int ii=0; ii<msgUnitArr.length; ii++) {
         MsgUnitRaw msgUnit = msgUnitArr[ii];
         updateOneway(cbSessionId, msgUnit.getKey(), msgUnit.getContent(), msgUnit.getQos());
      }
   }

   /**
    * The class which extends AbstractCallbackExtended must implement this
    * method.
    * <p />
    * You receive one message, which is completely parsed and checked.
    *
    * @param cbSessionId The session ID specified by the client which registered the callback
    * @param updateKey   The arrived key (as an xml-string)
    * @param content     The arrived message content
    * @param updateQos   Quality of Service of the MsgUnitRaw as an xml-string
    * @see org.xmlBlaster.client.I_Callback
    */
   public abstract String update(String cbSessionId, UpdateKey updateKey, byte[] content,
                               UpdateQos updateQos) throws XmlBlasterException;
}
TOP

Related Classes of org.xmlBlaster.client.protocol.AbstractCallbackExtended

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.