plugin_registry.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:23k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: plugin_registry.cpp,v $
  4.  * PRODUCTION Revision 1000.8  2004/06/01 20:44:30  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: plugin_registry.cpp,v 1000.8 2004/06/01 20:44:30 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbidll.hpp>
  41. #include <corelib/ncbifile.hpp>
  42. #include <corelib/ncbimtx.hpp>
  43. #include <gui/core/algo_factory.hpp>
  44. #include <gui/core/obj_convert.hpp>
  45. #include <gui/core/plugin_exception.hpp>
  46. #include <gui/core/plugin_factory.hpp>
  47. #include <gui/core/plugin_registry.hpp>
  48. #include <gui/core/plugin_utils.hpp>
  49. #include <gui/core/version.hpp>
  50. #include <gui/plugin/PluginCache.hpp>
  51. #include <gui/plugin/PluginInfo.hpp>
  52. #include <gui/plugin/PluginLibInfo.hpp>
  53. #include <gui/utils/message_box.hpp>
  54. #include <serial/objostr.hpp>
  55. #include <serial/objistr.hpp>
  56. #include <serial/serial.hpp>
  57. #include "plugin_handle_impl.hpp"
  58. #include <algorithm>
  59. BEGIN_NCBI_SCOPE
  60. USING_SCOPE(objects);
  61. // typedef for our handle types (internal use only)
  62. typedef CRef<CPluginHandle_Impl> TPluginImpl;
  63. // functor for sorting plugin handles by content
  64. struct SPluginLessByClassName {
  65.     bool operator() (const TPluginImpl& h0, const TPluginImpl& h1) const
  66.     {
  67.         return (h0->GetClassName() < h1->GetClassName());
  68.     }
  69. };
  70. // functor for sorting plugin handles by menu name
  71. struct SPluginLessByMenuItem {
  72.     bool operator()(const TPluginImpl& h1, const TPluginImpl& h2) const
  73.     {
  74.         // sort first by menu item
  75.         if (h1->GetMenuItem() < h2->GetMenuItem()) {
  76.             return true;
  77.         }
  78.         if (h1->GetMenuItem() > h2->GetMenuItem()) {
  79.             return false;
  80.         }
  81.         // we always pass empty menu items - their sort order is unimportant
  82.         if (h1->GetMenuItem().empty()) {
  83.             return true;
  84.         }
  85.         // sort next by class name
  86.         if (h1->GetClassName() < h2->GetClassName()) {
  87.             return true;
  88.         }
  89.         if (h1->GetClassName() > h2->GetClassName()) {
  90.             return false;
  91.         }
  92.         // sort finally by class name
  93.         return (h1->GetCommand() < h2->GetCommand());
  94.     }
  95. };
  96. typedef set<TPluginImpl, SPluginLessByMenuItem> TPluginRegistry;
  97. // our plugin registry
  98. static TPluginRegistry s_PluginRegistry;
  99. // mutex protecting access to the registry
  100. DEFINE_STATIC_MUTEX(s_PluginRegistryMutex);
  101. //
  102. // read the plugin cache in the specified directory and add its contents to the
  103. // current registry
  104. //
  105. void CPluginRegistry::InitPlugins(const string& path)
  106. {
  107.     string cache_file(path + CDirEntry::GetPathSeparator() + "plugin-cache");
  108.     {{
  109.          // first, check to see if the plugin cache exists
  110.          CFile file(cache_file);
  111.          if ( !file.Exists() ) {
  112.              LOG_POST(Info <<
  113.                       "CPluginRegistry::InitPlugins(): "
  114.                       "no plugin cache found at " << cache_file);
  115.              return;
  116.          }
  117.      }}
  118.     // try reading in ASN.1 text format
  119.     try {
  120.         auto_ptr<CObjectIStream> is
  121.             (CObjectIStream::Open(eSerial_AsnText, cache_file));
  122.         CRef<CPluginCache> cache(new CPluginCache());
  123.         *is >> *cache;
  124.         LOG_POST(Info
  125.                  << "CPluginRegistry::InitPlugins(): plugin cache found in "
  126.                  << path);
  127.         x_InitPlugins(path, *cache);
  128.         return;
  129.     }
  130.     catch (CException& _DEBUG_ARG(e)) {
  131.         _TRACE("read of ASN.1 text plugin cache in "
  132.                << path << " failed: " << e.what());
  133.     }
  134.     // on error, try reading in ASN.1 binary format
  135.     try {
  136.         auto_ptr<CObjectIStream> is
  137.             (CObjectIStream::Open(eSerial_AsnBinary, cache_file));
  138.         CRef<CPluginCache> cache(new CPluginCache());
  139.         *is >> *cache;
  140.         LOG_POST(Info
  141.                  << "CPluginRegistry::InitPlugins(): plugin cache found in "
  142.                  << path);
  143.         x_InitPlugins(path, *cache);
  144.         return;
  145.     }
  146.     catch (CException& _DEBUG_ARG(e)) {
  147.         _TRACE("read of ASN.1 binary plugin cache in "
  148.                << path << " failed: " << e.what());
  149.     }
  150.     // if not, try reading in XML
  151.     try {
  152.         auto_ptr<CObjectIStream> is
  153.             (CObjectIStream::Open(eSerial_Xml, cache_file));
  154.         CRef<CPluginCache> cache(new CPluginCache());
  155.         *is >> *cache;
  156.         LOG_POST(Info
  157.                  << "CPluginRegistry::InitPlugins(): plugin cache found in "
  158.                  << path);
  159.         x_InitPlugins(path, *cache);
  160.         return;
  161.     }
  162.     catch (CException& _DEBUG_ARG(e)) {
  163.         _TRACE("read of XML plugin cache in "
  164.                << path << " failed: " << e.what());
  165.     }
  166.     // log an error and continue...
  167.     LOG_POST(Error
  168.              << "CPluginRegistry: No plugins found in directory " << path);
  169. }
  170. void CPluginRegistry::x_InitPlugins(const string& path, CPluginCache& cache)
  171. {
  172.     CMutexGuard LOCK(s_PluginRegistryMutex);
  173.     //
  174.     // now, process our plugin info objects
  175.     //
  176.     TPlugins plugins;
  177.     int plug_count = s_PluginRegistry.size();
  178.     NON_CONST_ITERATE (CPluginCache::Tdata, iter, cache.Set()) {
  179.         CPluginLibInfo& libinfo = **iter;
  180.         string lib_path = (path + CDirEntry::GetPathSeparator() +
  181.                            libinfo.GetLibrary());
  182.         libinfo.SetLibrary(lib_path);
  183.         CPluginHandle handle = AddPlugin(libinfo, eNonPersistent);
  184.         plugins.push_back(handle);
  185.     }
  186.     //
  187.     // ping any autoload commands now
  188.     //
  189.     NON_CONST_ITERATE (TPlugins, iter, plugins) {
  190.         CPluginHandle handle = *iter;
  191.         if ( !handle.GetInfo().CanGetAutorun()  ||
  192.              !handle.GetInfo().GetAutorun() ) {
  193.             continue;
  194.         }
  195.         _TRACE("autoloading " << handle.GetInfo().GetClass_name());
  196.         const CPluginInfo::TCommands& cmds =
  197.             handle.GetInfo().GetCommands();
  198.         try {
  199.             switch (cmds.Which()) {
  200.             case CPluginCommandSet::e_Algo:
  201.                 ITERATE (CPluginInfo::TCommands::TAlgo, cmd_iter,
  202.                          cmds.GetAlgo()) {
  203.                     CRef<CPluginMessage> msg(new CPluginMessage);        
  204.                     CPluginRequest& request = msg->SetRequest();
  205.                     handle.FillDefaults
  206.                         ((EAlgoCommand)(*cmd_iter)->GetCommand(),
  207.                          request.SetAlgo());
  208.                     handle.Execute(*msg);
  209.                 }
  210.                 break;
  211.             case CPluginCommandSet::e_View:
  212.                 break;
  213.             case CPluginCommandSet::e_Data:
  214.                 break;
  215.             default:
  216.                 break;
  217.             }
  218.         }
  219.         catch (CException& e) {
  220.             LOG_POST(Error << "Error running autoload commands: "
  221.                      << e.what());
  222.         }
  223. #ifndef _DEBUG
  224.         catch (...) {
  225.             LOG_POST(Error << "Unknown error running autoload commands");
  226.         }
  227. #endif
  228.     }
  229.     LOG_POST(Info << "  registered "
  230.              << s_PluginRegistry.size() - plug_count
  231.              << " plugins in path " << path);
  232. }
  233. void CPluginRegistry::Clear(void)
  234. {
  235.     CMutexGuard LOCK(s_PluginRegistryMutex);
  236.     s_PluginRegistry.clear();
  237. }
  238. void CPluginRegistry::RegisterPlugin(CRef<CPluginInfo> info,
  239.                                      CPluginFactoryBase *factory)
  240. {
  241.     CMutexGuard LOCK(s_PluginRegistryMutex);
  242.     // build a PluginLibInfo from info
  243.     CRef<CPluginLibInfo> libinfo(new CPluginLibInfo);
  244.     libinfo->SetInfo(*info);
  245.     string lib_path = "NONE";
  246.     libinfo->SetLibrary(lib_path);
  247.     // make a plugin handle from this
  248.     TPluginImpl handle(new CPluginHandle_Impl(*libinfo));
  249.     // set the factory
  250.     handle->x_SetFactory(factory);
  251.     // register the plugin
  252.     TPluginRegistry::iterator reg_iter = s_PluginRegistry.find(handle);
  253.     if (reg_iter != s_PluginRegistry.end()) {
  254.         LOG_POST(Warning
  255.                  << "Overriding "
  256.                  << libinfo->GetInfo().GetClass_name()
  257.                  << " with equivalent plugin from "
  258.                  << libinfo->GetLibrary());
  259.         s_PluginRegistry.erase(reg_iter);
  260.     }
  261.     s_PluginRegistry.insert(handle);
  262. }
  263. CPluginHandle CPluginRegistry::AddPlugin(CPluginLibInfo& libinfo,
  264.                                          EUserPlugin mode)
  265. {
  266.     TPluginImpl impl(new CPluginHandle_Impl(libinfo));
  267.     TPluginRegistry::iterator reg_iter = s_PluginRegistry.find(impl);
  268.     if (reg_iter != s_PluginRegistry.end()) {
  269.         LOG_POST(Warning
  270.                  << "Overriding "
  271.                  << libinfo.GetInfo().GetClass_name()
  272.                  << " with equivalent plugin from "
  273.                  << libinfo.GetLibrary());
  274.         s_PluginRegistry.erase(reg_iter);
  275.     }
  276.     s_PluginRegistry.insert(impl);
  277.     switch (mode) {
  278.     case ePersistent:
  279.         break;
  280.     default:
  281.     case eNonPersistent:
  282.         break;
  283.     }
  284.     return impl->GetHandle();
  285. }
  286. template <class Command, class BufferObj>
  287. CPluginRegistry::TPlugins
  288. s_GetPlugins(const TPluginRegistry& registry, Command cmd,
  289.              const BufferObj* obj, int flags)
  290. {
  291.     // Some compilers (*cough*WorkShop*cough*) don't allow templates
  292.     // to access statics, so we must use registry rather than
  293.     // s_PluginRegistry here.
  294.     CConvertCache cache;
  295.     CPluginRegistry::TPlugins plugins;
  296.     ITERATE (TPluginRegistry, iter, registry) {
  297.         const CPluginHandle_Impl& handle = **iter;
  298.         CPluginCommand args;
  299.         if ( !handle.IsEnabled() ) {
  300.             continue;
  301.         }
  302.         if ( (flags & CPluginRegistry::fHidden) == 0  &&
  303.              handle.GetMenuItem().empty()) {
  304.             continue;
  305.         }
  306.         if ( !handle.FillDefaults(cmd, args) ) {
  307.             continue;
  308.         }
  309.         /**
  310.         FIXME: this causes too many problems, and will be temporarily disabled
  311.         it is *very* time-consuming on large records
  312.         if (CPluginUtils::CanFitArgs(args.SetArgs(), *obj, &cache)) {
  313.             plugins.push_back((*iter)->GetHandle());
  314.         }
  315.         **/
  316.         plugins.push_back((*iter)->GetHandle());
  317.     }
  318.     return plugins;
  319. }
  320. //
  321. // retrieve plugins specific for a given command and valid for a given document
  322. //
  323. CPluginRegistry::TPlugins
  324. CPluginRegistry::GetPlugins(EAlgoCommand cmd, TFlags flags)
  325. {
  326.     CMutexGuard LOCK(s_PluginRegistryMutex);
  327.     return s_GetPlugins(s_PluginRegistry, cmd, (const IDocument*)NULL, flags);
  328. }
  329. CPluginRegistry::TPlugins
  330. CPluginRegistry::GetPlugins(EDataCommand cmd, const IDocument* doc,
  331.                             TFlags flags)
  332. {
  333.     CMutexGuard LOCK(s_PluginRegistryMutex);
  334.     return s_GetPlugins(s_PluginRegistry, cmd, doc, flags);
  335. }
  336. CPluginRegistry::TPlugins
  337. CPluginRegistry::GetPlugins(EViewCommand cmd, TFlags flags)
  338. {
  339.     CMutexGuard LOCK(s_PluginRegistryMutex);
  340.     return s_GetPlugins(s_PluginRegistry, cmd, (const IDocument*)NULL, flags);
  341. }
  342. //
  343. // retrieve plugins specific for a set of objects
  344. //
  345. CPluginRegistry::TPlugins
  346. CPluginRegistry::GetPlugins(EDataCommand cmd, const CSelectionBuffer& buf,
  347.                             TFlags flags)
  348. {
  349.     CMutexGuard LOCK(s_PluginRegistryMutex);
  350.     return s_GetPlugins(s_PluginRegistry, cmd, &buf, flags);
  351. }
  352. //
  353. // retrieve all plugins
  354. //
  355. CPluginHandle CPluginRegistry::GetPlugin(const string& name)
  356. {
  357.     CMutexGuard LOCK(s_PluginRegistryMutex);
  358.     ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
  359.         if ((*iter)->IsEnabled()  &&  (*iter)->GetClassName() == name) {
  360.             return (*iter)->GetHandle();
  361.         }
  362.     }
  363.     _TRACE("CPluginRegistry::GetPlugin(): failed to find plugin " << name);
  364.     return CPluginHandle();
  365. }
  366. //
  367. // retrieve all plugins
  368. //
  369. CPluginRegistry::TPlugins CPluginRegistry::GetPlugins(TFlags flags)
  370. {
  371.     CMutexGuard LOCK(s_PluginRegistryMutex);
  372.     TPlugins plugins;
  373.     ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
  374.         if ( (flags & fHidden) == 0  && (*iter)->GetMenuItem().empty()) {
  375.             continue;
  376.         }
  377.         if ((*iter)->IsEnabled()) {
  378.             plugins.push_back((*iter)->GetHandle());
  379.         }
  380.     }
  381.     return plugins;
  382. }
  383. //
  384. // retrieve plugins valid for a given command type
  385. //
  386. CPluginRegistry::TPlugins
  387. CPluginRegistry::GetPlugins(CPluginCommandSet::E_Choice cmd, TFlags flags)
  388. {
  389.     CMutexGuard LOCK(s_PluginRegistryMutex);
  390.     TPlugins plugins;
  391.     ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
  392.         if ( (flags & fHidden) == 0  && (*iter)->GetMenuItem().empty()) {
  393.             continue;
  394.         }
  395.         if ( (*iter)->GetCommand() == cmd  &&  (*iter)->IsEnabled()) {
  396.             plugins.push_back((*iter)->GetHandle());
  397.         }
  398.     }
  399.     return plugins;
  400. }
  401. void CPluginRegistry::x_LoadLibrary(const string& lib)
  402. {
  403.     CMutexGuard LOCK(s_PluginRegistryMutex);
  404.     string dir;
  405.     string base;
  406.     string ext;
  407.     CDirEntry::SplitPath(lib, &dir, &base, &ext);
  408.     CDll dll(dir, base + ext, CDll::eLoadLater);
  409.     try {
  410.         dll.Load();
  411.         LOG_POST(Info << "loaded plugin library " << base + ext);
  412.         // grab the single entry point
  413.         list<CPluginFactoryBase*> plugins;
  414.         CPluginFactoryBase::FPluginEntryPoint get_plugins =
  415.             dll.GetEntryPoint_Func("NCBIGBenchGetPlugins", &get_plugins);
  416.         if ( !get_plugins ) {
  417.             NCBI_THROW(CPluginException, ePluginLoadFailed,
  418.                        "Library is not a valid plug-in");
  419.         }
  420.         // grab our plugin factories
  421.         get_plugins(plugins);
  422.         ITERATE (list<CPluginFactoryBase*>, iter, plugins) {
  423.             CPluginFactoryBase* factory = *iter;
  424.             if ( !factory ) {
  425.                 continue;
  426.             }
  427.             // check for version information
  428.             //CPluginRequest request;
  429.             //request.SetInfo();
  430.             //CPluginReply reply;
  431.             //factory->RunCommand(request, reply);
  432.             //if ( reply.GetStatus() != eRequestStatus_success  ||
  433.             //     !reply.GetAction().IsInfo() ) {
  434.             //    // the plugin factory doesn't support the 'info' command
  435.             //    continue;
  436.             //}
  437.             // make sure our library is set...
  438.             CPluginInfo info;
  439.             (*iter)->GetInfo(info);
  440.             //const CPluginInfo& info = reply.GetAction().GetInfo();
  441.             if ( !CPluginVersion::CheckVersion(info.GetVer_major(),
  442.                                                info.GetVer_minor()) ) {
  443.                 string msg = "Version Mismatch:nframework version ";
  444.                 msg += NStr::IntToString(CPluginVersion::eMajor);
  445.                 msg += "." + NStr::IntToString(CPluginVersion::eMinor);
  446.                 msg += " : plugin version ";
  447.                 msg += NStr::IntToString(info.GetVer_major());
  448.                 msg += "." + NStr::IntToString(info.GetVer_minor());
  449.                 msg += ", rev " + NStr::IntToString(info.GetVer_revision());
  450.                 msg += "nplugin build date: " + info.GetVer_build_date();
  451.                 NCBI_THROW(CPluginException, eVersionMismatch, msg);
  452.             }
  453.             // retrieve and process all commands
  454.             // we will fill in details for plugin handles as we go
  455.             TPluginRegistry::iterator plug_iter = s_PluginRegistry.begin();
  456.             for ( ;  plug_iter != s_PluginRegistry.end();  ++plug_iter) {
  457.                 if ( (*plug_iter)->GetClassName() == info.GetClass_name() ) {
  458.                     (*plug_iter)->x_SetFactory(factory);
  459.                     LOG_POST(Info
  460.                              << "registering plugin " << info.GetClass_name());
  461.                     break;
  462.                 }
  463.             }
  464.             if (plug_iter == s_PluginRegistry.end()) {
  465.                 LOG_POST(Warning
  466.                          << "failed to register plugin "
  467.                          << (*plug_iter)->GetClassName());
  468.             }
  469.         }
  470.     }
  471.     catch(CException& e) {
  472.         dll.Unload();
  473.         string msg("Failed to load plugin library ");
  474.         msg += base + ext;
  475.         msg += ":n";
  476.         msg += e.GetMsg();
  477.         NcbiMessageBox(msg);
  478.     }
  479. #ifndef _DEBUG
  480.     catch (...) {
  481.         dll.Unload();
  482.         string msg("Failed to load plugin library ");
  483.         msg += base + ext;
  484.         msg += ":nUnknown error.";
  485.         NcbiMessageBox(msg);
  486.     }
  487. #endif
  488. }
  489. END_NCBI_SCOPE
  490. /*
  491.  * ===========================================================================
  492.  * $Log: plugin_registry.cpp,v $
  493.  * Revision 1000.8  2004/06/01 20:44:30  gouriano
  494.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
  495.  *
  496.  * Revision 1.45  2004/05/21 22:27:40  gorelenk
  497.  * Added PCH ncbi_pch.hpp
  498.  *
  499.  * Revision 1.44  2004/04/16 14:38:28  dicuccio
  500.  * Eliminated APIs from GetPlugins() that would perform selection-based sieving -
  501.  * they were not used
  502.  *
  503.  * Revision 1.43  2004/03/16 15:59:50  vasilche
  504.  * Removed warning about unused exception variable
  505.  *
  506.  * Revision 1.42  2004/01/27 18:32:10  dicuccio
  507.  * Added default handler to switch
  508.  *
  509.  * Revision 1.41  2004/01/06 14:24:03  dicuccio
  510.  * Temporarily disable the use of CanFitArgs() inside of GetPlugins() when all
  511.  * that is known is a document - the search is very expensive on big records.
  512.  *
  513.  * Revision 1.40  2003/12/09 15:44:53  dicuccio
  514.  * Use CException::GetMsg() instead of what()
  515.  *
  516.  * Revision 1.39  2003/12/03 12:40:05  dicuccio
  517.  * Restore auto-processing of autorun plugins
  518.  *
  519.  * Revision 1.38  2003/11/26 17:06:56  dicuccio
  520.  * Dropped autoloading of plugins - favor explicit initialization
  521.  *
  522.  * Revision 1.37  2003/11/24 15:39:40  dicuccio
  523.  * Renamed CVersion to CPluginVersion
  524.  *
  525.  * Revision 1.36  2003/11/19 18:15:14  ucko
  526.  * Adjust for CDll API change.
  527.  *
  528.  * Revision 1.35  2003/11/06 20:06:29  dicuccio
  529.  * Moved USING_SCOPE(objects) to implementation files
  530.  *
  531.  * Revision 1.34  2003/11/04 17:19:07  dicuccio
  532.  * Added Clear().  CHanged to patch API change in CPluginMessage
  533.  *
  534.  * Revision 1.33  2003/10/27 17:37:51  dicuccio
  535.  * Better diagnostics for exceptions in reading plugin cache
  536.  *
  537.  * Revision 1.32  2003/10/25 16:03:37  dicuccio
  538.  * Removed debugging output that disabled plugin reading on Unix
  539.  *
  540.  * Revision 1.31  2003/10/23 16:17:03  dicuccio
  541.  * Added API to add user-defined plugins
  542.  *
  543.  * Revision 1.30  2003/10/10 17:15:33  dicuccio
  544.  * Changed sort params for plugin handles - now, sort by menu item.  Added object
  545.  * conversion cache to plugin retrieval.  Removed unnecessary sort()s.
  546.  *
  547.  * Revision 1.29  2003/09/30 23:48:04  ucko
  548.  * s_GetPlugins: re-fixed WorkShop build, and added a comment explaining
  549.  * how to stay out of trouble.
  550.  *
  551.  * Revision 1.28  2003/09/30 13:40:12  dicuccio
  552.  * Added sorting of plugins by menu name
  553.  *
  554.  * Revision 1.27  2003/09/04 14:01:51  dicuccio
  555.  * Introduce IDocument and IView as abstract base classes for CDocument and CView
  556.  *
  557.  * Revision 1.26  2003/08/05 17:07:15  dicuccio
  558.  * Changed calling semantics for the message queue - pass by reference, not
  559.  * CConstRef<>
  560.  *
  561.  * Revision 1.25  2003/07/28 18:27:38  jcherry
  562.  * Added CPluginRegistry::RegisterPlugin for registering external
  563.  * (executable) plugins
  564.  *
  565.  * Revision 1.24  2003/07/25 19:45:22  shomrat
  566.  * Immediately execute autorun plugins
  567.  *
  568.  * Revision 1.23  2003/07/21 19:28:37  dicuccio
  569.  * Added retrieval of plugins based on contents of a selection buffer
  570.  *
  571.  * Revision 1.22  2003/07/14 11:01:16  shomrat
  572.  * Plugin messageing system related changes
  573.  *
  574.  * Revision 1.21  2003/07/09 12:29:21  dicuccio
  575.  * (Finally!) fixed build issues on WorkShop - removed accessing of all static
  576.  * variables from inside local templated functions
  577.  *
  578.  * Revision 1.20  2003/06/30 13:33:15  dicuccio
  579.  * Added API to screen out "empty" plugins
  580.  *
  581.  * Revision 1.19  2003/06/30 11:29:34  dicuccio
  582.  * Moved access of mutex out of template (WorkShop compiler doesn't like this)
  583.  *
  584.  * Revision 1.18  2003/06/29 13:10:17  dicuccio
  585.  * Use DEFINE_STATIC_MUTEX() instead of static member variables
  586.  *
  587.  * Revision 1.17  2003/06/25 17:02:54  dicuccio
  588.  * Split CPluginHandle into a handle (pointer-to-implementation) and
  589.  * implementation file.  Lots of #include file clean-ups.
  590.  *
  591.  * Revision 1.16  2003/06/20 14:47:41  dicuccio
  592.  * Revised handling of plugin registration (moved GetInfo() out of plugin
  593.  * factory and into each handler as a static function)
  594.  *
  595.  * Revision 1.15  2003/05/30 14:15:41  dicuccio
  596.  * Renamed MessageBox to NcbiMessageBox because brain-dead MSVC thinks this is
  597.  * ::MessageBox and rewrites the symbol as MessageBoxA, which results in an
  598.  * unresolved external and conflict with the Win32 API :(.
  599.  *
  600.  * Revision 1.14  2003/05/30 12:56:50  dicuccio
  601.  * Converted code to use MessageBox() instead of
  602.  * fl_ask()/fl_message()/fl_alert()
  603.  *
  604.  * Revision 1.13  2003/05/19 13:35:59  dicuccio
  605.  * Moved gui/core/plugin/ -> gui/plugin/.  Merged gui/core/algo, gui/core/doc/,
  606.  * and gui/core/view/ into one library (gui/core/)
  607.  *
  608.  * Revision 1.12  2003/05/08 16:18:59  dicuccio
  609. * Changed CFastMutex --> CMutex - guards against recursive locking
  610. *
  611. * Revision 1.11  2003/05/06 15:54:51  dicuccio
  612. * Added mutex to guard access to plugin registry
  613. *
  614. * Revision 1.10  2003/04/29 14:41:18  dicuccio
  615. * Removed old GetPlugins() call - use new command-based API
  616. *
  617. * Revision 1.9  2003/03/31 13:47:50  dicuccio
  618. * Changed standard start-up messages to be more comprehensible
  619. *
  620. * Revision 1.8  2003/03/25 13:11:10  dicuccio
  621. * Fixed compilation issue on compaq compiler - don't redeclare loop variable
  622. * 'iter' inside of loop
  623. *
  624. * Revision 1.7  2003/03/13 18:15:48  dicuccio
  625. * Added accessor for a single, named plugin.  Changed registration to
  626. * explicitly allow overriding of plugins
  627. *
  628. * Revision 1.6  2003/03/10 22:58:51  kuznets
  629. * iterate -> ITERATE
  630. *
  631. * Revision 1.5  2003/02/28 15:06:55  dicuccio
  632. * Added check to see if a plugin is enabled
  633. *
  634. * Revision 1.4  2003/02/24 13:03:15  dicuccio
  635. * Renamed classes in plugin spec:
  636. *     CArgSeg --> CPluginArgSet
  637. *     CArgument --> CPluginArg
  638. *     CPluginArgs --> CPluginCommand
  639. *     CPluginCommands --> CPluginCommandSet
  640. *
  641. * Revision 1.3  2003/02/21 17:16:52  dicuccio
  642. * Fixed compilation errors related to changes in plugin architecture
  643. *
  644. * Revision 1.2  2003/02/20 20:35:45  dicuccio
  645. * Fixed compilation errors after commit of plugin architecture changes
  646. *
  647. * Revision 1.1  2003/02/20 19:49:56  dicuccio
  648. * Created new plugin architecture, based on ASN.1 spec.  Moved GBENCH frameowrk
  649. * over to use new plugin architecture.
  650. *
  651. * ===========================================================================
  652. */