Package org.xmlBlaster.engine.mime

Source Code of org.xmlBlaster.engine.mime.PublishPluginManager

/*------------------------------------------------------------------------------
Name:      PublishPluginManager.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
Comment:   Code for a plugin manager for persistence
Version:   $Id: PublishPluginManager.java 16883 2008-04-29 10:27:55Z ruff $
Author:    goetzger@gmx.net
------------------------------------------------------------------------------*/
package org.xmlBlaster.engine.mime;

import java.util.logging.Logger;
import java.util.logging.Level;
import org.xmlBlaster.engine.runlevel.I_RunlevelListener;
import org.xmlBlaster.engine.runlevel.RunlevelManager;
import org.xmlBlaster.util.plugin.PluginManagerBase;
import org.xmlBlaster.util.plugin.PluginInfo;
import org.xmlBlaster.util.plugin.I_Plugin;
import org.xmlBlaster.util.XmlBlasterException;
import org.xmlBlaster.engine.ServerScope;
import org.xmlBlaster.util.def.Constants;

import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;

/**
* Loads publish() filter plugin depending on message MIME type.
* Please register your plugins in xmlBlaster.properties, for example:
* <pre>
* MimePublishPlugin[MyFilter][1.0]=com.mycompany.MyFilter
* </pre>
*/
public class PublishPluginManager extends PluginManagerBase implements I_RunlevelListener {

   private final String ME;
   private static final String defaultPluginName = null; // "org.xmlBlaster.engine.mime.demo.DemoFilter
   public static final String pluginPropertyName = "MimePublishPlugin";

   private final ServerScope glob;
   private static Logger log = Logger.getLogger(PublishPluginManager.class.getName());

   /** Map holds the known plugins */
   private final Map pluginMap = new TreeMap();
   /** Cache for up to now arrived message mime types */
   private final Map mimeCache = new TreeMap();
   /** A dummy object which we put into the mimeCache if no plugins are found */
   private final Object dummyObject = new Object();
   /** To avoid huge caches if every message sends crazy different mime types */
   private final int maxMimeCacheSize;

   public PublishPluginManager(ServerScope glob) throws XmlBlasterException {
      super(glob);
      this.glob = glob;
      this.ME = "PublishPluginManager" + this.glob.getLogPrefixDashed();

      this.maxMimeCacheSize = glob.getProperty().get("MimePublishPlugin.maxMimeCacheSize", 1000);
      glob.getRunlevelManager().addRunlevelListener(this);
   }

   /** Called from base class after creation */
   public void postInstantiate(I_Plugin plugin_, PluginInfo pluginInfo) {
      I_PublishFilter plugin = (I_PublishFilter)plugin_;
      plugin.initialize(glob);
      if (pluginMap.get(plugin.getName()) != null)
         log.warning("Instantiating publish filter plugin '" + plugin.getName() + "' again, have you configured it twice?");
        
      pluginMap.put(plugin.getName(), plugin);
      if (log.isLoggable(Level.FINE)) log.fine("Instantiated publish filter plugin '" + plugin.getName() + "'");
   }

   /**
    * Instantiate all given plugins from xmlBlaster.properties.
    * <p />
    * E.g.
    * <code>MimePublishPlugin[PublishLenChecker][1.0]=org.xmlBlaster.engine.mime.demo.PublishLenChecker,DEFAULT_MAX_LEN=200</code>
    * <p />
    * If invoked again, the loaded plugins are reset and reloaded with the current property settings
    */
   public synchronized void initializePlugins() throws XmlBlasterException {
      pluginMap.clear();
      mimeCache.clear();
      Map map = glob.getProperty().get(pluginPropertyName, (Map)null);
      if (map != null) {
         Iterator iterator = map.keySet().iterator();
         while (iterator.hasNext()) {
            String key = (String)iterator.next(); // contains "PublishFilterLen:1.0", the type and version are separated by a ":"
            String type = key.substring(0, key.indexOf(":"));
            String version = key.substring(key.indexOf(":")+1);
            I_PublishFilter plugin = (I_PublishFilter)getPluginObject(type, version);
            if (plugin == null) {
               log.severe("Problems accessing plugin " + PublishPluginManager.pluginPropertyName + "[" + type + "][" + version +"] please check your configuration");
            }
         }
         log.info("Instantiated " + pluginMap.size() + " publish filter plugins");
      }
      else {
         if (log.isLoggable(Level.FINE)) log.fine("No plugins configured with 'MimePublishPlugin'");
      }
   }

   /**
    * Are there any plugins?
    */
   public final boolean hasPlugins() {
      return pluginMap.size() > 0;
   }

   /**
    * @return null if no plugin for this mime type found, otherwise a map with I_PublishFilter
    * objects (= matching plugins) is returned
    */
   public synchronized Map findMimePlugins(String mime, String mimeExtended) {
      if (pluginMap.size() == 0)
         return null;

      if (mime == null) {
         Thread.dumpStack();
         throw new IllegalArgumentException("You must pass a valid contentMime type");
      }
      if (mimeExtended == null || mimeExtended.length() < 1) mimeExtended = Constants.DEFAULT_CONTENT_MIME_EXTENDED;
      String key = mime + mimeExtended;

      // First we check the cache ...
      Object ret = mimeCache.get(key);
      if (ret != null && ret instanceof Map)
         return (Map)ret;
      else if (ret != null && ret instanceof Object)
         return null// dummy object to indicate that such messages have no plugin

      if (log.isLoggable(Level.FINE)) log.fine("mime=" + mime + " mimeExtended=" + mimeExtended + " not found in cache, searching the plugin ...");
     
      if (mimeCache.size() > maxMimeCacheSize) {
         log.warning("Cache has reached max size of " + maxMimeCacheSize + " entries, erasing entries");
         mimeCache.clear(); // This way we avoid very old entries and memory exhaust
      }

      // This is the first message of this mime type, add to cache ...
     
      Iterator iterator = pluginMap.values().iterator();
      while (iterator.hasNext()) {
         I_PublishFilter plugin = (I_PublishFilter)iterator.next();
         String[] mimes = plugin.getMimeTypes();
         String[] extended = plugin.getMimeExtended();
         if (mimes == null || extended == null || mimes.length != extended.length) {
            String text = "Your plugin '" + plugin.getName() + "' must pass a valid mime type with a corresponding mimeExtended type, plugin ignored.";
            log.severe(text);
            Thread.dumpStack();
            throw new IllegalArgumentException(text);
         }
         for (int ii=0; ii<mimes.length; ii++) {
            if (mimes[ii].equals("*") ||
                mimes[ii].equals(mime) &&
                  (extended[ii].equals("*") || extended[ii].equals(mimeExtended))) {
               // Ok, found a plugin, add it to cache
               Map plugins = (Map)mimeCache.get(key);
               if (plugins == null) { // we need a multimap, sadly JDK does not offer it, so we use a map in the map.
                  plugins = new TreeMap();
                  mimeCache.put(key, plugins);
               }
               plugins.put(plugin.getName(), plugin);
               log.info("mime=" + mime + " mimeExtended=" + mimeExtended + " added to cache with plugin=" + plugin.getName());
               break;
            }
         }
      }

      Object plugins = mimeCache.get(key);
      if (plugins == null) {
         mimeCache.put(key, dummyObject);
         log.info("mime=" + mime + " mimeExtended=" + mimeExtended + " added to cache, no plugin is available");
         return null;
      }
      if (plugins instanceof Map)
         return (Map)plugins;
      return null;
   }

   /**
   * @return The name of the property in xmlBlaster.property "MimePublishPlugin"
   * for "MimePublishPlugin[demo][1.0]"
   */
   protected String getPluginPropertyName() {
      return pluginPropertyName;
   }

   /**
    * @return please return your default plugin classname or null if not specified
    */
   public String getDefaultPluginName(String type, String version) {
      return defaultPluginName;
   }

   public void shutdown() {
      Iterator iterator = pluginMap.values().iterator();
      while (iterator.hasNext()) {
         I_PublishFilter plugin = (I_PublishFilter)iterator.next();
         plugin.shutdown();
      }
      pluginMap.clear();
      mimeCache.clear();
   }

   /**
    * A human readable name of the listener for logging.
    * <p />
    * Enforced by I_RunlevelListener
    */
   public String getName() {
      return ME;
   }

   /**
    * Invoked on run level change, see RunlevelManager.RUNLEVEL_HALTED and RunlevelManager.RUNLEVEL_RUNNING
    * <p />
    * Enforced by I_RunlevelListener
    */
   public void runlevelChange(int from, int to, boolean force) throws org.xmlBlaster.util.XmlBlasterException {
      //if (log.isLoggable(Level.FINER)) log.call(ME, "Changing from run level=" + from + " to level=" + to + " with force=" + force);
      if (to == from)
         return;

      if (to > from) { // startup
         if (to == RunlevelManager.RUNLEVEL_STANDBY) {
            initializePlugins();
         }
      }
      if (to < from) { // shutdown
         if (to == RunlevelManager.RUNLEVEL_HALTED) {
            shutdown();
         }
      }
   }
}
TOP

Related Classes of org.xmlBlaster.engine.mime.PublishPluginManager

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.