Package org.xmlBlaster.engine

Source Code of org.xmlBlaster.engine.SessionPersistencePlugin

/*------------------------------------------------------------------------------
Name:      SessionPersistencePlugin.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/

package org.xmlBlaster.engine;

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

import org.xmlBlaster.authentication.ClientEvent;
import org.xmlBlaster.authentication.SessionInfo;
import org.xmlBlaster.engine.msgstore.I_ChangeCallback;
import org.xmlBlaster.engine.msgstore.I_Map;
import org.xmlBlaster.engine.msgstore.I_MapEntry;
import org.xmlBlaster.engine.qos.AddressServer;
import org.xmlBlaster.engine.qos.ConnectQosServer;
import org.xmlBlaster.engine.qos.ConnectReturnQosServer;
import org.xmlBlaster.engine.queuemsg.SessionEntry;
import org.xmlBlaster.engine.queuemsg.SubscribeEntry;
import org.xmlBlaster.util.SessionName;
import org.xmlBlaster.util.Timestamp;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.util.def.Constants;
import org.xmlBlaster.util.def.ErrorCode;
import org.xmlBlaster.util.key.KeyData;
import org.xmlBlaster.util.key.QueryKeyData;
import org.xmlBlaster.util.plugin.PluginInfo;
import org.xmlBlaster.util.qos.ClientProperty;
import org.xmlBlaster.util.qos.ConnectQosData;
import org.xmlBlaster.util.qos.QueryQosData;
import org.xmlBlaster.util.qos.storage.QueuePropertyBase;
import org.xmlBlaster.util.qos.storage.SessionStoreProperty;
import org.xmlBlaster.util.qos.storage.SubscribeStoreProperty;
import org.xmlBlaster.util.queue.I_Entry;
import org.xmlBlaster.util.queue.I_EntryFilter;
import org.xmlBlaster.util.queue.I_Storage;
import org.xmlBlaster.util.queue.StorageId;

/**
* SessionPersistencePlugin provides the persistent storage for both sessions
* and subscriptions.
*
* @author <a href="mailto:michele@laghi.eu">Michele Laghi</a>
*/
public class SessionPersistencePlugin implements I_SessionPersistencePlugin {

   private final static String ME = "SessionPersistencePlugin";
   /** when recovering all subscriptions must be 'noInitialUpdate' because otherwise
    * we would get messages which we already got in the past
    */
   private final static String ORIGINAL_INITIAL_UPDATES = "__originalInitialUpdates";

   private PluginInfo info;
   private ServerScope global;
   private static Logger log = Logger.getLogger(SessionPersistencePlugin.class.getName());

   /** flag indicating the status: true means initialized and not yet shut down) */
   private boolean isOK;

   private I_Map sessionStore;
   private I_Map subscribeStore;
   private StorageId sessionStorageId;
   private StorageId subscribeStorageId;
   private AddressServer addressServer;
   private Object sync = new Object();

   private int duplicateCounter;
   private int errorCounter;

   /**
    *
    * @return hash map containing the secret sessionId of the entries recovered
    *         as values and as keys the corresponding absolute name for the session (String)
    * @throws XmlBlasterException
    */
   private HashMap recoverSessions() throws XmlBlasterException {
      I_MapEntry[] entries = this.sessionStore.getAll(null);
      HashMap sessionIds = new HashMap();
      for (int i=0; i < entries.length; i++) {
       try {
           if (entries[i] instanceof SessionEntry) {
              // do connect
              SessionEntry entry = (SessionEntry)entries[i];
              ConnectQosData data = this.global.getConnectQosFactory().readObject(entry.getQos());

              this.addressServer = new AddressServer(this.global, "NATIVE", this.global.getId(), (java.util.Properties)null);

              ConnectQosServer qos = new ConnectQosServer(this.global, data);
              qos.isFromPersistenceRecovery(true);
              qos.setPersistenceUniqueId(entry.getUniqueId());
              qos.setAddressServer(this.addressServer);

              SessionName sessionName = data.getSessionName();
              String sessionId = data.getSessionQos().getSecretSessionId();
              sessionIds.put(sessionName.getAbsoluteName(), sessionId);
              if (log.isLoggable(Level.FINE))
                 log.fine("recoverSessions: store in map session='" + sessionName.getAbsoluteName() + "' has secret sessionId='" + sessionId + "' and persistenceUniqueId=" + entry.getUniqueId());
              // if (log.isLoggable(Level.FINE)) log.trace(ME, "recoverSessions: session: '" + data.getSessionName() + "' secretSessionId='" + qos.getSessionQos().getSecretSessionId() + "' qos='" + qos.toXml() + "'");
              ConnectReturnQosServer ret = this.global.getAuthenticate().connect(qos);
              if (log.isLoggable(Level.FINEST))
                 log.finest("recoverSessions: return of connect: returnConnectQos='" + ret.toXml() + "'");
           }
           else {
              throw new XmlBlasterException(this.global, ErrorCode.INTERNAL_ILLEGALARGUMENT, ME + ".recoverSessions: the entry in the storage should be of type 'SessionEntry' but is of type'" + entries[i].getClass().getName() + "'");
           }
        }
        catch (XmlBlasterException e) { // authenticate password changed? TODO
          log.warning("Loading session from persistency failed: " + e.toString());
        }
      }
      return sessionIds;
   }


   /**
    * When recovering due to a run level change (without shutting down the
    * application) this will not work.
    *
    * @throws XmlBlasterException
    */
   private void recoverSubscriptions(final HashMap sessionIds) throws XmlBlasterException {
      {
         boolean checkForDuplicateSubscriptions = this.global.getProperty().get("xmlBlaster/checkForDuplicateSubscriptions", false);
         if (checkForDuplicateSubscriptions) {
            duplicateCounter = 0;
            errorCounter = 0;
            final java.util.Map duplicates = new java.util.TreeMap();
            /*I_MapEntry[] results = */this.subscribeStore.getAll(new I_EntryFilter() {
               public I_Entry intercept(I_Entry entry, I_Storage storage) {
                  if (storage.isTransient()) return null;
                  try {
                     SubscribeEntry subscribeEntry = (SubscribeEntry)entry;
                     //QueryKeyData keyData = queryKeyFactory.readObject(subscribeEntry.getKey());
                     QueryQosData qosData = global.getQueryQosFactory().readObject(subscribeEntry.getQos());
                     //String key = keyData.getOid() + qosData.getSender().getAbsoluteName();

                     SessionName sessionName = new SessionName(global, subscribeEntry.getSessionName());
                     Object found = sessionIds.get(sessionName.getAbsoluteName());
                     if (found == null) {
                        if (errorCounter == 0) {
                           log.warning("Ignoring invalid entry '" + sessionName.getAbsoluteName() + "' as user is not known");
                        }
                        errorCounter++;
                        return null;
                     }

                     String key = qosData.getSubscriptionId();
                     if (log.isLoggable(Level.FINE))
                        log.fine("Cleanup of duplicate subscriptions, key=" + key);
                     if (duplicates.containsKey(key)) {
                        if (duplicateCounter == 0)
                           log.warning("Cleanup of duplicate subscriptions, this may take a while, please wait ...");
                        duplicateCounter++;
                        //log.warn(ME, "Removing duplicate subscription '" + key + "' oid=" + keyData.getOid());
                        //subscribeStore.remove(subscribeEntry);
                     }
                     else {
                        duplicates.put(key, subscribeEntry);
                     }
                  }
                  catch (XmlBlasterException e) {
                     log.severe("Ignoring unexpected problem in checkForDuplicateSubscriptions :" + e.toString());
                  }
                  return null;
               }
            });
            if (duplicateCounter > 0) {
               this.subscribeStore.clear();
               if (this.subscribeStore.getNumOfEntries() > 0)
                     log.severe("Internal prpblem with checkForDuplicateSubscriptions");
               java.util.Iterator it = duplicates.keySet().iterator();
               while (it.hasNext()) {
                  this.subscribeStore.put((I_MapEntry)duplicates.get(it.next()));
               }
               log.warning("Removed " + (duplicateCounter-duplicates.size()) + " identical subscriptions, keeping " + duplicates.size() + ". Ignored " + errorCounter + " invalid subscriptions as no session was found");
            }
         }
      }

      I_MapEntry[] entries = this.subscribeStore.getAll(null);

      for (int i=0; i < entries.length; i++) {
         if (entries[i] instanceof SubscribeEntry) {
            // do connect
            SubscribeEntry entry = (SubscribeEntry)entries[i];
            String qos = entry.getQos();
            QueryQosData qosData = global.getQueryQosFactory().readObject(qos);

            ClientProperty clientProperty = qosData.getClientProperty(Constants.PERSISTENCE_ID);
            if (clientProperty == null) {
               log.severe("SubscribeQos with missing " + Constants.PERSISTENCE_ID + ": " + qosData.toXml());
               long uniqueId = new Timestamp().getTimestamp();
               qosData.getClientProperties().put(Constants.PERSISTENCE_ID, new ClientProperty(Constants.PERSISTENCE_ID, "long", null, "" + uniqueId));
            }

            boolean initialUpdates = qosData.getInitialUpdateProp().getValue();
            if (initialUpdates) {
               qosData.getClientProperties().put(ORIGINAL_INITIAL_UPDATES, new ClientProperty(ORIGINAL_INITIAL_UPDATES, "boolean", null, "true"));
            }
            SessionName sessionName = new SessionName(this.global, entry.getSessionName());
            String sessionId = (String)sessionIds.get(sessionName.getAbsoluteName());
            if (sessionId == null) {
               log.severe("The persistent session '" + sessionName.getAbsoluteName() + "' is not found, removing persistent subscription " + entry.getLogId());
               this.subscribeStore.remove(entry);
               continue;
               //throw new XmlBlasterException(this.global, ErrorCode.INTERNAL_NULLPOINTER, ME + ".recoverSubscriptions", "The secret sessionId was not found for session='" + sessionName.getAbsoluteName() + "'");
            }
            // TODO remove the setting of client properties and invoke directly requestBroker.subscribe with subscribeQosServer.inhibitInitialUpdates(true);
            // also get the sessionInfo object from authenticate => eliminate sessionIds
            this.global.getAuthenticate().getXmlBlaster().subscribe(this.addressServer, sessionId, entry.getKey(), qosData.toXml());
         }
         else {
            throw new XmlBlasterException(this.global, ErrorCode.INTERNAL_ILLEGALARGUMENT, ME + ".recoverSubscriptions: the entry in the storage should be of type 'SubscribeEntry'but is of type'" + entries[i].getClass().getName() + "'");
         }
      }
   }

   private void removeAssociatedSubscriptions(SessionInfo sessionInfo)
      throws XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("removeAssociatedSubscriptions for session '" + sessionInfo.getId() + "'");
      XmlBlasterException e = null;
      SubscriptionInfo[] subs = this.global.getRequestBroker().getClientSubscriptions().getSubscriptions(sessionInfo);
      for (int i=0; i < subs.length; i++) {
         try {
            if (log.isLoggable(Level.FINER)) log.finer("removeAssociatedSubscriptions for session '" + sessionInfo.getId() + "' subscription '" + subs[i].getId() + "'");
            this.subscriptionRemove(new SubscriptionEvent(subs[i]));
         }
         catch (XmlBlasterException ex) {
            if (e == null) e = ex;
            log.severe("removeAssociatedSubscriptions: exception occured for session '" + sessionInfo.getId() + "' and subscriptions '" + subs[i].getId() + "' : ex: " + ex.getMessage());
         }
      }
      // just throw the first exception encountered (if any)
      if (e != null) throw e;
   }


   /**
    * Initializes the 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)
      throws XmlBlasterException {
      synchronized (this.sync) {
         if (this.isOK) return;
         this.info = pluginInfo;
         this.global = (org.xmlBlaster.engine.ServerScope)glob;

         if (log.isLoggable(Level.FINER))
            log.finer("init");

         // init the storages
         QueuePropertyBase sessionProp = new SessionStoreProperty(this.global, this.global.getStrippedId());
         if (sessionProp.getMaxEntries() > 0L) {
            String type = sessionProp.getType();
            String version = sessionProp.getVersion();
            // NEW: "heron", "session", "subPersistence,1.0"
            this.sessionStorageId = new StorageId(glob, this.global.getDatabaseNodeStr(), Constants.RELATING_SESSION,
                  this.info.getId());
            // OLD: "session", "heron/subPersistence,1.0"
            // this.sessionStorageId = new StorageId(glob,
            // Constants.RELATING_SESSION, this.global.getStrippedId() +"/" +
            // this.info.getId());
            // -> OLD: xb_entries.queuename="session_heronsubPersistence,1_0"
            this.sessionStore = this.global.getStoragePluginManager().getPlugin(type, version, this.sessionStorageId, sessionProp);
         }
         else {
            if (log.isLoggable(Level.FINE))
               log.fine(Constants.RELATING_SESSION + " persistence for session is switched off with maxEntries=0");
         }
         QueuePropertyBase subscribeProp = new SubscribeStoreProperty(this.global, this.global.getStrippedId());
         if (subscribeProp.getMaxEntries() > 0L) {
            String type = subscribeProp.getType();
            String version = subscribeProp.getVersion();
            this.subscribeStorageId = new StorageId(glob, this.global.getDatabaseNodeStr(),
                  Constants.RELATING_SUBSCRIBE,
                  this.info.getId());
            // id from xmlBlasterPlugins.xml: "subPersistence,1_0"
            // this.subscribeStorageId = new StorageId(glob,
            // Constants.RELATING_SUBSCRIBE, this.global.getStrippedId() +"/" +
            // this.info.getId());
            this.subscribeStore = this.global.getStoragePluginManager().getPlugin(type, version, this.subscribeStorageId, subscribeProp);
         }
         else if (log.isLoggable(Level.FINE))
            log.fine(Constants.RELATING_SUBSCRIBE + " persistence for subscribe is switched off with maxEntries=0");
         this.isOK = true;

         // register before having retreived the data since needed to fill info objects with persistenceId
         this.global.getRequestBroker().getAuthenticate().addClientListener(this);
         this.global.getRequestBroker().addSubscriptionListener(this);
         log.fine("Recovering Sessions");
         HashMap sessionIds = recoverSessions();
         log.fine("Recovering Subscriptions");
         recoverSubscriptions(sessionIds);
         log.fine("Recovering of Subscriptions finished");
      }

      //The topics restored from persistence didn't switch on the destroyTimeout to not diappear until we are finished
      this.global.getTopicAccessor().spanTopicDestroyTimeout();
   }

   /**
    * returns the plugin type
    * @see org.xmlBlaster.util.plugin.I_Plugin#getType()
    */
   public String getType() {
      if (this.info != null) return this.info.getType();
      return null;
   }

   /**
    * returns the plugin version
    * @see org.xmlBlaster.util.plugin.I_Plugin#getVersion()
    */
   public String getVersion() {
      if (this.info != null) return this.info.getVersion();
      return null;
   }

   /**
    * Shutsdown the plugin
    * @see org.xmlBlaster.util.plugin.I_Plugin#shutdown()
    */
   public void shutdown() throws XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("shutdown");
      synchronized (this.sync) {
         this.isOK = false;
         this.global.getRequestBroker().getAuthenticate().removeClientListener(this);
         this.global.getRequestBroker().removeSubscriptionListener(this);
         this.sessionStore.shutdown();
         this.subscribeStore.shutdown();
      }
   }

   /**
    * A new session is added, checks if it shall be persisted.
    */
   private void addOrUpdateSession(final SessionInfo sessionInfo) throws XmlBlasterException {

      final ConnectQosData connectQosData = sessionInfo.getConnectQos().getData();

      // Is transient?
      if (connectQosData.getPersistentProp() == null || !connectQosData.getPersistentProp().getValue()) return;

      // Avoid recursion
      if (sessionInfo.getConnectQos().isFromPersistenceRecovery()) return;

      if (sessionInfo.getSessionName().isPubSessionIdInternal()) { // negative pubSessionId?
         log.warning("To use persistent session/subscriptions you should login with a given publicSessionId, see http://www.xmlblaster.org/xmlBlaster/doc/requirements/engine.persistence.session.html");
      }

      // Persist it
      StorageId storageId = null;
      if (sessionInfo.getPersistenceUniqueId() == 0) {
         long uniqueId = new Timestamp().getTimestamp(); // new session
         SessionEntry entry = new SessionEntry(connectQosData.toXml(), uniqueId, connectQosData.size(), storageId);
         if (log.isLoggable(Level.FINE)) log.fine("addSession (persistent) for NEW uniqueId: '" + entry.getUniqueId() + "'");
         sessionInfo.setPersistenceUniqueId(uniqueId);
         this.sessionStore.put(entry);
      }
      else {
         // session exists? -> update
         final long uniqueId = sessionInfo.getPersistenceUniqueId();
         this.sessionStore.change(uniqueId, new I_ChangeCallback() {
            public I_MapEntry changeEntry(I_MapEntry mapEntry)
                  throws XmlBlasterException {
               SessionEntry sessionEntry = new SessionEntry(connectQosData.toXml(), uniqueId, connectQosData.size(),
                     null);
               if (log.isLoggable(Level.FINE)) log.fine("changeSession (persistent) for uniqueId: '" + sessionEntry.getUniqueId() + "'");
               return sessionEntry;
            }
         });
      }
   }

   /**
    *
    * @see org.xmlBlaster.authentication.I_ClientListener#sessionAdded(org.xmlBlaster.authentication.ClientEvent)
    */
   public void sessionAdded(ClientEvent e) throws XmlBlasterException {
      if (!this.isOK) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_UNAVAILABLE, ME + ".sessionAdded: invoked when plugin already shut down");
      SessionInfo sessionInfo = e.getSessionInfo();
      addOrUpdateSession(sessionInfo);
   }
  
   /**
    * Invoked on successful client re-login (interface I_ClientListener)
    */
   public void sessionUpdated(ClientEvent e) throws XmlBlasterException
   {
      if (log.isLoggable(Level.FINER)) log.finer("Session update event for client " + e.getSessionInfo().toString());
      ConnectQosServer previous = e.getPreviousConnectQosServer();
      ConnectQosServer connectQos = e.getConnectQos();
      if (previous == null || connectQos == null)
         return;
      if (connectQos.isFromPersistenceRecovery())
         return;
      if (e.getSessionInfo() == null)
         return;
      if (previous.getData().isPersistent() && !connectQos.getData().isPersistent()) {
         log.warning("Ignoring change from persistence true to false for " + e.getSessionInfo().getId());
      }
      else {
         // Update other qos property changes in persistence
         this.addOrUpdateSession(e.getSessionInfo());
      }
   }

   public void sessionRemoved(ClientEvent e) throws XmlBlasterException {
   }

   /**
    *
    * @see org.xmlBlaster.authentication.I_ClientListener#sessionRemoved(org.xmlBlaster.authentication.ClientEvent)
    */
   public void sessionPreRemoved(ClientEvent e) throws XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("sessionRemoved '" + e.getSessionInfo().getId() + "'");
      if (!this.isOK) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_UNAVAILABLE, ME + ".sessionRemoved: invoked when plugin already shut down");

      SessionInfo sessionInfo = e.getSessionInfo();
      ConnectQosData connectQosData = sessionInfo.getConnectQos().getData();
      if (!connectQosData.getPersistentProp().getValue()) return;

      removeAssociatedSubscriptions(sessionInfo);

      // TODO add a method I_Queue.removeRandom(long uniqueId)
      long uniqueId = sessionInfo.getPersistenceUniqueId();
      if (log.isLoggable(Level.FINE)) log.fine("sessionRemoved (persistent) for uniqueId: '" + uniqueId + "'");
      // String sessionId = getOriginalSessionId(connectQosData.getSessionQos().getSecretSessionId());
      SessionEntry entry = new SessionEntry(connectQosData.toXml(), uniqueId, 0L, null);
      int num = this.sessionStore.remove(entry);
      if (num != 1) {
         XmlBlasterException ex = sessionInfo.getTransportConnectFail();
         if (ex != null)
            log.fine("sessionRemoved (persistent) for uniqueId: '" + uniqueId + "' failed, entry not found.");
         else
            log.severe("sessionRemoved (persistent) for uniqueId: '" + uniqueId + "' failed, entry not found.");
      }
   }

   /**
    * This event is invoked even by child subscriptions. However only
    * parent subscriptions should be stored, so all child subscriptions are
    * ignored.
    * @see org.xmlBlaster.engine.I_SubscriptionListener#subscriptionAdd(org.xmlBlaster.engine.SubscriptionEvent)
    */
   public void subscriptionAdd(SubscriptionEvent e) throws XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("subscriptionAdd '" + e.getSubscriptionInfo().getId() + "'");
      if (!this.isOK) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_UNAVAILABLE, ME + ".subscriptionAdded: invoked when plugin already shut down");
      //Thread.dumpStack();

      SubscriptionInfo subscriptionInfo = e.getSubscriptionInfo();
      KeyData data = subscriptionInfo.getKeyData();
      // if (!(data instanceof QueryKeyData)) return; // this filters away child subscriptions
      if (subscriptionInfo.isCreatedByQuerySubscription()) return;

      // TODO add a method I_Queue.removeRandom(long uniqueId)
      QueryQosData subscribeQosData = subscriptionInfo.getQueryQosData();
      if (log.isLoggable(Level.FINEST)) log.finest("subscriptionAdd: key='" + data.toXml() + "'");
      if (subscribeQosData != null) if (log.isLoggable(Level.FINEST)) log.finest("subscriptionAdd: qos='" + subscribeQosData.toXml() + "'");
      if (subscribeQosData == null || !subscribeQosData.isPersistent()) return;

      SessionInfo sessionInfo = subscriptionInfo.getSessionInfo();
      if (!sessionInfo.getConnectQos().getData().isPersistent()) {
         sessionInfo.getConnectQos().getData().setPersistent(true);
         this.addOrUpdateSession(sessionInfo);
      }

      // is it a remote connect ?
      ClientProperty clientProperty = subscribeQosData.getClientProperty(Constants.PERSISTENCE_ID);
      if (clientProperty == null) {
         long uniqueId = new Timestamp().getTimestamp();
         subscribeQosData.getClientProperties().put(Constants.PERSISTENCE_ID, new ClientProperty(Constants.PERSISTENCE_ID, "long", null, "" + uniqueId));
         QueryKeyData subscribeKeyData = (QueryKeyData)data;

         // to be found when the client usubscribes after a server crash ...
         subscribeQosData.setSubscriptionId(subscriptionInfo.getSubscriptionId());
         SubscribeEntry entry = new SubscribeEntry(subscribeKeyData.toXml(), subscribeQosData.toXml(), sessionInfo
               .getConnectQos().getSessionName().getAbsoluteName(), uniqueId, 0L, null);
         if (log.isLoggable(Level.FINE)) log.fine("subscriptionAdd: putting to persistence NEW entry '" + entry.getUniqueId() + "' key='" + subscribeKeyData.toXml() + "' qos='" + subscribeQosData.toXml() + "' secretSessionId='" + sessionInfo.getSecretSessionId() + "'");
         subscriptionInfo.setPersistenceId(uniqueId);
         this.subscribeStore.put(entry);
      }
      else  {    // ... or from a recovery ?
         // TODO handle by recoverSubscriptions(..)
         // No remove: To avoid danger of looping we keep the marker (Marcel 2005-08-08)
         //   subscribeQosData.getClientProperties().remove(Constants.PERSISTENCE_ID);

         long uniqueId = clientProperty.getLongValue();
         if (log.isLoggable(Level.FINE)) log.fine("subscriptionAdd: filling OLD uniqueId into subscriptionInfo '" + uniqueId + "'");
         subscriptionInfo.setPersistenceId(uniqueId);
         ClientProperty prop = subscribeQosData.getClientProperty(ORIGINAL_INITIAL_UPDATES);
         if (prop != null) {
            if (subscriptionInfo.getSubscribeQosServer() != null) {
               subscriptionInfo.getSubscribeQosServer().inhibitInitalUpdates(true);
               subscribeQosData.getClientProperties().remove(ORIGINAL_INITIAL_UPDATES);
            }
         }
      }
   }

   /**
    *
    * @see org.xmlBlaster.engine.I_SubscriptionListener#subscriptionRemove(org.xmlBlaster.engine.SubscriptionEvent)
    */
   public void subscriptionRemove(SubscriptionEvent e)
      throws XmlBlasterException {
      if (log.isLoggable(Level.FINER)) log.finer("subscriptionRemove '" + e.getSubscriptionInfo().getId() + "'");
      if (!this.isOK) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_UNAVAILABLE, ME + ".subscriptionRemove: invoked when plugin already shut down");

      SubscriptionInfo subscriptionInfo = e.getSubscriptionInfo();
      KeyData keyData = subscriptionInfo.getKeyData();
      if (!(keyData instanceof QueryKeyData)) {
         if (log.isLoggable(Level.FINE)) log.fine("subscriptionRemove keyData wrong instance'");
         return;
      }
      if (subscriptionInfo.getPersistenceId() < 1L) {
         return;
      }
      // TODO add a method I_Queue.removeRandom(long uniqueId)
      QueryQosData qosData = subscriptionInfo.getQueryQosData();
      if (qosData == null || qosData.getPersistentProp() == null || !qosData.getPersistentProp().getValue()) {
         return;
      }

      this.subscribeStore.remove(subscriptionInfo.getPersistenceId());
      /*
      SubscribeEntry entry = new SubscribeEntry(keyData.toXml(), qosData.toXml(), subscriptionInfo.getSessionInfo().getConnectQos().getSessionName().getAbsoluteName(), subscriptionInfo.getPersistenceId(), 0L);
      if (log.isLoggable(Level.FINE)) log.trace(ME, "subscriptionRemove: removing from persistence entry '" + entry.getUniqueId() + "' secretSessionId='" + subscriptionInfo.getSessionInfo().getConnectQos().getSessionName().getAbsoluteName());
      this.subscribeStore.remove(entry);
      */
   }

   /**
    * does nothing
    */
   public void subjectAdded(ClientEvent e) throws XmlBlasterException {
   }
   /**
    * does nothing
    */
   public void subjectRemoved(ClientEvent e) throws XmlBlasterException {
   }

   /**
    * @see org.xmlBlaster.engine.I_SubscriptionListener#getPriority()
    */
   public Integer getPriority() {
      return PRIO_10;
   }
}
TOP

Related Classes of org.xmlBlaster.engine.SessionPersistencePlugin

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.