Package net.fp.rp.search.mid.global

Source Code of net.fp.rp.search.mid.global.PluginManager$PluginThread

/*
* Copyright (C) 2004 Paul Browne, http://www.firstpartners.net,
* built with the help of Fast-Soft (fastsoftdev@yahoo.com)
*
* released under terms of the GPL license
* http://www.opensource.org/licenses/gpl-license.php
*
* This product includes software developed by the
* Apache Software Foundation (http://www.apache.org)."
*
* This product includes software developed by the
* Spring Framework Project (http://www.springframework.org)."
*
*/
package net.fp.rp.search.mid.global;

import java.io.File;
import java.io.FileFilter;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;

import net.fp.rp.common.exception.RpException;
import net.fp.rp.search.back.extractor.convertor.IDocumStructConvertor;
import net.fp.rp.search.back.struct.DocumStruct;
import net.fp.rp.search.common.util.Util;
import net.fp.rp.search.mid.loader.RPClassLoader;
import net.fp.rp.search.plugins.ICategoryManager;
import net.fp.rp.search.plugins.ICategoryStore;
import net.fp.rp.search.plugins.IDataExtractor;
import net.fp.rp.search.plugins.IFeedbackDataStore;
import net.fp.rp.search.plugins.IIndexManager;
import net.fp.rp.search.plugins.INewInformation;
import net.fp.rp.search.plugins.IPlugin;
import net.fp.rp.search.plugins.events.IInterestedInAdd;
import net.fp.rp.search.plugins.events.IInterestedInFeedback;
import net.fp.rp.search.plugins.events.IInterestedInResultsFilter;
import net.fp.rp.search.plugins.events.IInterestedInSearch;

import org.apache.log4j.Logger;
import org.apache.commons.codec.binary.Base64;

/**
* Central point to get handle to the plugins available to the system<BR/> This
* one propogates Events to the loaded plugins.
*
* @author Firstpartners.net
* @version 1.1
* Copyright @link www.firstpartners.net/red
*/
public class PluginManager {
    /** Logger for this class and subclasses */
    protected final static Logger logger =  Logger.getLogger(PluginManager.class);

    /** Root plugins  */
    private String root;

    /** Category manager  */
    private static ICategoryManager categoryManager;

    /** Index manager */
    private static IIndexManager indexManager;

    /** Category store  */
    private static ICategoryStore categoryStores;

    /** Feedback store */
    private static IFeedbackDataStore feedbackDataStores;

    /** List of plugins interested in add */
    private static LinkedList m_listPluginsInAdd;

    /** List of plugins interested in feedback */
    private static LinkedList m_listPluginsInFeedback;

    /** List of plugins interested in filter */
    private static LinkedList m_listPluginsInFilter;

    /** List of plugins interested in search */
    private static LinkedList m_listPluginsInSearch;

    /** List of plugins interested in extract data */
    private static LinkedList m_listPluginsInExtract;

    /** User credentials */
    private static String m_encodedCredentials = null;

    /** Proxy configuration */
    private Proxy proxy = null;

    /** List of plugins which belongs to the system */
    private Collection plugins;

    /** List of the running plugins ( controlled in the search process ) */
    private static LinkedList m_listRunningPlugins;
   
  /** Actual class loader which extends the tomcat.class loader */
  private static RPClassLoader  m_loader  =null;
 
  /** Flag to indicate that search processs is active */
  private int countSearch = 0;
 
  /**
   * Gives a chance to modify the search data before it is indexed
   */
  private static IDocumStructConvertor documStructConvertor=null;
 
    /**
     * Creates a new PluginManager object.
     */
    protected PluginManager() {
        //instantiate here the required variables
        m_listPluginsInAdd = new LinkedList();
        m_listPluginsInFeedback = new LinkedList();
        m_listPluginsInFilter = new LinkedList();
        m_listPluginsInSearch = new LinkedList();
        m_listPluginsInExtract = new LinkedList();

        m_listRunningPlugins = new LinkedList();
        m_encodedCredentials = null;
    }

    /**
     * 'Walks' Directory Tree from point X (specified in config file) and loads
     * all classes that implement the IPlugin interface. Holds these as
     * internal Cache for the other methods on this class to query for
     * specific plugin types (e.g. getDataSources / getMetaDataStores).
     *
     * @throws RpException If an error must to be signaled
     */
    void loadPlugins() throws RpException {
        logger.info("Start to load the plugins ");

        //set the actual rp class loader
        m_loader = new RPClassLoader( this.getClass().getClassLoader() );

        //Atention here must to set also the Proxy data (general configuration)
        if (proxy != null) {
            if (!(Util.isEmpty(proxy.getHost())) &&
                    !(Util.isEmpty(proxy.getPort()))) {
                //set the proxy data
                logger.info("Proxy configuration was required ");
                System.getProperties().put("proxySet", "true");
                System.getProperties().put("proxyHost", proxy.getHost());
                System.getProperties().put("proxyPort", proxy.getPort());

                if (!(Util.isEmpty(proxy.getUser())) &&
                        !(Util.isEmpty(proxy.getPassword()))) {
                    logger.info(
                        " Proxy configuration with credentials was required ");

                    String credential = proxy.getUser() + ":" +
                        proxy.getPassword();
                   //was: this is deprecated in Java 6 m_encodedCredentials = new sun.misc.BASE64Encoder().encode(credential.getBytes());
                    byte[] encodedBytes  = Base64.encodeBase64(credential.getBytes());
                    m_encodedCredentials = new String(encodedBytes);
                   // String decodedString = new String(Base64.decodeBase64(encodedBytes));
               
                }
            }
        }

        
        logger.info("Detect the system plugin types ... ");
        //iterate on the plugin list and call in background the onLoad process
        Iterator it = plugins.iterator();

        while (it.hasNext()) {
            //get the list of specialized plugins (InAdd,InSearch....
            //Attention one plugin can implement 2 or more specialized interfaces.
            Object plugin = it.next();

            if ( isPlugin (plugin)) {
               
              logger.info("Detected Plugin of Type:"+plugin.getClass());
              PluginThread background = new PluginThread((IPlugin) plugin);
                background.setPriority( Thread.MAX_PRIORITY );
                background.start();

            } else {
                logger.warn("The specified class:" +
                    plugin.getClass().getName() +
                    " is not a plugin will be ignored");
            }
        }

        //add the category and index manager to the plugin list
        isPlugin(indexManager);
        isPlugin(categoryManager);

        //load the index& category manager
        indexManager.onLoad();
        if(categoryManager!=null){
          categoryManager.onLoad();
        }
         
        logger.info("Load the external plugins ... ");

        //load the other plugins
        //Plugin defined in the other package/or extend class which implement IPLugin
        LinkedList otherPlugins = new LinkedList();
        logger.info("Root is " + root);
        //detect the plugins from extensible plugins folder and added to the default plugin list

        if ( ! Util.isEmpty( root )) {
            //plugins folder
            File pluginFolder = new File(root);

            logger.info("Process the plugins file" + pluginFolder);
            if (pluginFolder.isDirectory() && pluginFolder.exists()) {
                 File[] list = pluginFolder.listFiles( new FileFilter() {
                      public boolean accept(File arg0) {
                              // TODO Auto-generated method stub
                            logger.info("PRoces" + arg0.getName());
                              if ( arg0.getName().endsWith(".class"))//later extension for jar and zip
                                      return true;
                              else
                                      return false;
                      }
                 });

                 //parse the list
                 for (int i=0;i< list.length; i++)
                 {
                     logger.info("Process the file path:" + list[i].getPath() +" Name:"+list[i].getName() );
                     logger.info("Class name is "+ list[i].getName().substring(0, list[i].getName().indexOf(".") ));
                     try {
                         m_loader.addClassFile ( list[i] );
                         //add the object to the plugin list

                         Object plugin = m_loader.loadAppClass( list[i].getName().substring(0, list[i].getName().indexOf(".")) ).newInstance();
                         //add the object to the plugin list
                         otherPlugins.add( plugin );
                     }
                     catch (ClassNotFoundException e){
                         logger.warn("Error in getting the class "+e.getMessage());
                     }
                     catch (InstantiationException e){
                         logger.debug("Error in instantiation process"+e.getMessage());
                     }
                     catch (IllegalAccessException e){
                         logger.debug("Error in instantiation process"+e.getMessage());
                     }
                 }
            }
         }
        it = otherPlugins.iterator();

        while (it.hasNext()) {
            //get the list of specialized plugins (InAdd,InSearch....
            //Attention one plugin can implement 2 or more specialized interfaces.
            Object plugin = it.next();

            if ( isPlugin (plugin)) {
                PluginThread background = new PluginThread((IPlugin) plugin);
                background.setPriority( Thread.MAX_PRIORITY );
                background.start();

            } else {
                logger.warn("The specified class:" +
                    plugin.getClass().getName() +
                    " is not a plugin will be ignored");
            }
        }
    }

    /**
     * Validate if the specified object is a plugin (implement one of the
     * default IPlugin interfaces). If yes, also the detect the plugin type
     * 
     * @param plugin  Plugin object to validate
     * @return True if the object is a plugin object, false otherwise
     */
    private boolean isPlugin( Object plugin) {
     
      //Null check
      if(plugin==null){
        logger.debug("Plugin is null");
        return false;
      }
       
       
        Class pluginClass =plugin.getClass();
        logger.debug("Detect the type of the plugin class" +
                pluginClass.getName());
       
        boolean isPlugin = false;
        if ( plugin instanceof IInterestedInAdd ){
          addPluginTypeInAdd( (IInterestedInAdd) plugin );
          logger.debug("Plugin: " + pluginClass.getName() +
              " implement InAdd interface");
          isPlugin = true;
        }
      if ( plugin instanceof IInterestedInFeedback ){
            addPluginTypeInFeedback((IInterestedInFeedback) plugin);
            logger.debug("Plugin: " + plugin.getClass().getName() +
                " implement InFeedback interface");
            isPlugin = true;
      }
      if ( plugin instanceof IInterestedInResultsFilter){
            addPluginTypeInFilter((IInterestedInResultsFilter) plugin);
            logger.debug("Plugin: " + plugin.getClass().getName() +
                " implement InResultsFilter interface");
            isPlugin = true;
        }
      if ( plugin instanceof IInterestedInSearch){
            addPluginTypeInSearch((IInterestedInSearch) plugin);
            logger.debug("Plugin: " + plugin.getClass().getName() +
                " implement InSearch interface");
            isPlugin = true;
      }
      if ( plugin instanceof IDataExtractor){
            addPluginTypeInExtract((IDataExtractor) plugin);
            logger.debug("Plugin: " + plugin.getClass().getName() +
                " implement IDataExtractor interface");
            isPlugin = true;
      }
      if ( plugin instanceof IPlugin){
            logger.debug("Plugin: " + plugin.getClass().getName() +
                " implement IPlugin interface");
            isPlugin = true;
        }

        return isPlugin;
    }
   
   
    public static IDataExtractor getBestExtractor(final INewInformation addInfo) throws RpException{
        IDataExtractor extractor = null;
        int max = 0;
        IDataExtractor[] extractors = PluginManager.getDataExtractors();

        for (int j = 0; j < extractors.length; j++) {
            int val = extractors[j].canHandle(addInfo);

            if (val > max) {
                max = val;
                extractor = extractors[j];
            }
        }
        if (extractor != null) {
            Logger.getRootLogger().debug(
                "Best extractor for handling the information is :" +
                extractor.getClass().getName());

        } else {
            Logger.getRootLogger().warn(
                "No extractor is available for extract the data  " + addInfo.getUri());
        }
        return extractor;
    }
   
    /**
     * Add the document structure to the system
     *  
     * @param doc  DocumentStruct to be added to the system
     *
     * @return
     * @throws RpException
     */
    public static void storeAndAddDocument(DocumStruct doc)  {
     
      //Check if the configuration files says that the data should be modified
      if(documStructConvertor!=null){
        doc=documStructConvertor.modifyData(doc);
      }
     
     
      try {
          //store the document
          PluginManager.getCategoryStores().store( doc );
     
      //re-index the document
          PluginManager.getIndexManager().addToIndex( doc.getIndexDocument() );
      }
      catch (RpException e){
        logger.warn("Error in saving the document (as xml/index) ",e);
      }
    }
    /**
     * Get a handle to all the available DataStores (classes)
     *
     * @return single IBasicCategoryStore - as specified in the config file
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static ICategoryStore getCategoryStores() throws RpException {
        if (categoryStores != null) {
            return categoryStores;
        } else {
            throw new RpException("pluginmanager.plugins.nocategorystore");
        }
    }

    /**
     * Get a handle to the FeedbackDataStore
     *
     * @return IFeedbackDataStore (one per system , as per config file)
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IFeedbackDataStore getFeedbackDataStores()
        {
        if (feedbackDataStores != null) {
            return feedbackDataStores;
        } else {
          logger.debug("No Plugin Registered as being interested in Search Feedback");
          return null;
        }
    }

    /**
     * Get a handle to all the plugins interested in receiving feedback events
     *
     * @return array of IInterestedInFeedback - one for each plugin available.
     *         Guaranteed not to be null , zero length or contain any null
     *         elements in array.
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IInterestedInFeedback[] getInterestedInFeedback()
        throws RpException {
      
     
          
      if ((indexManager != null) ) {
            if ((m_listPluginsInFeedback != null) &&
                    (m_listPluginsInFeedback.size() > 0)) {
                IInterestedInFeedback[] list = new IInterestedInFeedback[m_listPluginsInFeedback.size()];
                m_listPluginsInFeedback.toArray(list);

                return list;
            } else {
                logger.debug("There are no configured plugins interested in Feedback");
              return new IInterestedInFeedback[0];
             
            }
        } else {
            throw new RpException("pluginmanager.noinit");
        }
    }

    /**
     * Get a handle to all the plugins interested in receiving add events
     *
     * @return array of IInterestedInFeedback - one for each plugin available.
     *         Guaranteed not to be null , but can be zero length or contain any null
     *         elements in array.
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IInterestedInAdd[] getInterestedInAdd()
        throws RpException {
      
     
     
      if ((indexManager != null) ) {
            if ((m_listPluginsInAdd != null) &&
                    (m_listPluginsInAdd.size() > 0)) {
                IInterestedInAdd[] list = new IInterestedInAdd[m_listPluginsInAdd.size()];
                m_listPluginsInAdd.toArray(list);

                return list;
            } else {
               logger.warn("No plugins are interested in Add events (apart from the Indexer)");
            //  return new IInterestedInAdd[0];
              throw new RpException("pluginmanager.plugins.noadd");
            }
        } else {
            throw new RpException("pluginmanager.noinit");
        }
    }

    /**
     * Get a handle to all the plugins interested in receiving Search Events
     *
     * @return array of IInterestedInFeedback - one for each plugin available.
     *         Guaranteed not to be null , zero length or contain any null
     *         elements in array.
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IInterestedInSearch[] getInterestedInSearch()
        throws RpException {
        if ((indexManager != null) ) {
            if ((m_listPluginsInSearch != null) &&
                    (m_listPluginsInSearch.size() > 0)) {
                IInterestedInSearch[] list = new IInterestedInSearch[m_listPluginsInSearch.size()];
                m_listPluginsInSearch.toArray(list);

                return list;
            } else {
                throw new RpException("pluginmanager.plugins.nosearch");
            }
        } else {
            throw new RpException("pluginmanager.noinit");
        }
    }

    /**
     * Get a handle to all the plugins interested in receiving feedback
     *
     * @return array of IInterestedInFeedback - one for each plugin available.
     *         Guaranteed not to be null , zero length or contain any null
     *         elements in array.
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IInterestedInResultsFilter[] getInterestedInFilterResults()
        throws RpException {
        if ((indexManager != null) && (categoryManager != null)) {
            if ((m_listPluginsInFilter != null) &&
                    (m_listPluginsInFilter.size() > 0)) {
                IInterestedInResultsFilter[] list = new IInterestedInResultsFilter[m_listPluginsInFilter.size()];
                m_listPluginsInFilter.toArray(list);

                return list;
            } else {
                throw new RpException("pluginmanager.plugins.nofilter");
            }
        } else {
            throw new RpException("pluginmanager.noinit");
        }
    }

    /**
     * Get a handle to all the plugins that can extract data
     *
     * @return array of IInterestedInFeedback - one for each plugin available.
     *         Guaranteed not to be null , zero length or contain any null
     *         elements in array.
     *
     * @throws RpException if there are no such plugins available at runtime
     */
    public static IDataExtractor[] getDataExtractors()
        throws RpException {
        if ((indexManager != null) && (categoryManager != null)) {
            if ((m_listPluginsInExtract != null) &&
                    (m_listPluginsInExtract.size() > 0)) {
                IDataExtractor[] list = new IDataExtractor[m_listPluginsInExtract.size()];
                m_listPluginsInExtract.toArray(list);

                return list;
            } else {
                throw new RpException("pluginmanager.plugins.noextractor");
            }
        } else {
            throw new RpException("pluginmanager.noinit");
        }
    }

    /**
     * Add the controller thread formed by plugin and information to the
     * running list in order to be controlled
     *
     * @param plugin
     * @param info
     */
    public static void addPluginThread(IInterestedInAdd plugin, INewInformation info,boolean useThreading) throws RpException {

     
      if(useThreading){
       
        logger.debug("Starting an Add Thread");
        //call the add in background
          ControllerThread control = new ControllerThread(plugin, info);
          control.setPriority(Thread.NORM_PRIORITY);
          control.start();
 
          //add the control thread to the list
          m_listRunningPlugins.add(control);
      } else {
        logger.debug("Calling Add, no thread");
        plugin.addInformation(info);
      }
     
    }

    /**
     * Validate if the system is in adding process
     *
     * @return True if exists one plugin which is running process
     */
    public static boolean isInAddProcess() {
        boolean result = false;
        int count = m_listRunningPlugins.size();

        //logger.info("Plugin has " + count +" plugins which are running ");
        for (int i = count - 1; i >= 0; i--) {
            Thread t = (Thread) m_listRunningPlugins.get(i);

            if (t.isAlive()) {
                result = true;

                break;
            }
        }

        return result;
    }

    /**
     * Set the low priority for the threads (a search is in running )
     */
    private void setPriority(final int priority ) {
        logger.info("Change the priority of the active plugins threads" );
        synchronized( m_listRunningPlugins ) {
            new Thread(new Runnable() {
                public void run() {
                    // TODO Auto-generated method stub
                    int count = m_listRunningPlugins.size();

                    for (int i = count - 1; i >= 0; i--) {
                        Thread t = (Thread) m_listRunningPlugins.get(i);

                        if (t.isAlive()) {
                            t.setPriority( priority );
                        } else {
                            logger.debug("Plugin finish the adding job" +
                                t.getName());
                            m_listRunningPlugins.remove( i );
                        }
                    }
                }
            }).start();
        }
    }
   
    /**
     * A new search operation was invoked into the system
     */
    public void startSearchOp(){
        synchronized ( this ){
            logger.debug("CounterSearch is " + countSearch);
          if (countSearch == 0) {
              //set all the thread priority to low
              setPriority( Thread.MIN_PRIORITY);
          }
          countSearch ++ ;
        }
    }

    /**
     * A search operation was finished
     */
    public void endSearchOp(){
        synchronized ( this ){
            logger.debug("CounterSearch is " + countSearch);
            countSearch--;
            if ( countSearch==0 ){
                //TODO Maybe is ok to set the High priority
                //set the priority to norm priority
                setPriority(Thread.NORM_PRIORITY);
            }
        }
    }

    /**
     * Add the plugin to InAdd list
     *
     * @param plugin Plugin object to be add
     */
    private void addPluginTypeInAdd(IInterestedInAdd plugin) {
      logger.debug("");
        m_listPluginsInAdd.add(plugin);
    }

    /**
     * Add the plugin to InFeedback list
     *
     * @param plugin Plugin object to be add
     */
    private void addPluginTypeInFeedback(IInterestedInFeedback plugin) {
        m_listPluginsInFeedback.add(plugin);
    }

    /**
     * Add the plugin to InFilter list
     *
     * @param plugin Plugin object to be add
     */
    private void addPluginTypeInFilter(IInterestedInResultsFilter plugin) {
        m_listPluginsInFilter.add(plugin);
    }

    /**
     * Add the plugin to the InSearch list
     *
     * @param plugin Plugin object to be add
     */
    private void addPluginTypeInSearch(IInterestedInSearch plugin) {
        m_listPluginsInSearch.add(plugin);
    }

    /**
     * Add the plugin to the InExtract list
     *
     * @param plugin Plugin object to be add
     */
    private void addPluginTypeInExtract(IDataExtractor plugin) {
        m_listPluginsInExtract.add(plugin);
    }

   
    /**
     * @return Returns the root.
     */
    public String getRoot() {
        return root;
    }
   
    /**
     * @param root The root to set.
     */
    public void setRoot(String root) {
        this.root = root;
    }
   
    /**
     * Get the proxy credentials in Base64 (sun) encoding
     *
     * @return
     */
    public static String getProxyCredentials() {
        return m_encodedCredentials;
    }

  /**
   * @return Returns the categoryManager.
   */
  public static ICategoryManager getCategoryManager() {
    return categoryManager;
  }
  /**
   * @param categoryManager The categoryManager to set.
   */
  public void setCategoryManager(ICategoryManager categoryManager) {
    PluginManager.categoryManager = categoryManager;
  }
  /**
   * @return Returns the indexManager.
   */
  public static IIndexManager getIndexManager() {
    return indexManager;
  }
  /**
   * @param indexManager The indexManager to set.
   */
  public void setIndexManager(IIndexManager indexManager) {
    PluginManager.indexManager = indexManager;
  }
  /**
   * @return Returns the plugins.
   */
  public Collection getPlugins() {
    return plugins;
  }
  /**
   * @param plugins The plugins to set.
   */
  public void setPlugins(Collection plugins) {
    logger.debug("Set Plugins Called: isNull? "+(plugins==null));
    this.plugins = plugins;
  }
  /**
   * @return Returns the proxy.
   */
  public Proxy getProxy() {
    return proxy;
  }
  /**
   * @param proxy The proxy to set.
   */
  public void setProxy(Proxy proxy) {
    this.proxy = proxy;
  }

  /**
   * @param proxy The CategoryStore to set.
   */
    public void setCategoryStores(ICategoryStore categoryStore) {
        PluginManager.categoryStores = categoryStore;
    }
   
    /**
   * @param proxy The FeedbackStore to set.
   */
    public void setFeedbackDataStores(IFeedbackDataStore feedbackDataStore) {
        PluginManager.feedbackDataStores = feedbackDataStore;
    }
  /**
   * @param documStructConvertor The documStructConvertor to set.
   */
  public void setDocumStructConvertor(IDocumStructConvertor documStructConvertor) {
    PluginManager.documStructConvertor = documStructConvertor;
  }

  /**
   * @return Returns the documStructConvertor.
   */
  public IDocumStructConvertor getDocumStructConvertor() {
    return documStructConvertor;
  }
  /**
     * This class is responsable for initialization of the plugin  Process of
     * initialzation (onLoad process ) will be made in background
     *
     * @author Firstpartners.net
     * @version 1.1
     */
    class PluginThread extends Thread {
        /** Plugin to run  */
        IPlugin m_plugin;

        /**
         * Creates a new PluginThread object.
         *
         * @param plugin
         */
        public PluginThread(IPlugin plugin) {
            m_plugin = plugin;
            logger.debug("Process the plugin : " + plugin.getClass().getName());
        }

        /**
         * Make the initialization of the plugin
         */
        public void run() {
            try {
                m_plugin.onLoad();
            } catch (RpException e) {
                logger.warn("Exception occured in loading the plugin" +
                    e.getMessage(), e);
            }
        }
    }
}
TOP

Related Classes of net.fp.rp.search.mid.global.PluginManager$PluginThread

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.