plugin_registry.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:23k
- /*
- * ===========================================================================
- * PRODUCTION $Log: plugin_registry.cpp,v $
- * PRODUCTION Revision 1000.8 2004/06/01 20:44:30 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: plugin_registry.cpp,v 1000.8 2004/06/01 20:44:30 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Mike DiCuccio
- *
- * File Description:
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbidll.hpp>
- #include <corelib/ncbifile.hpp>
- #include <corelib/ncbimtx.hpp>
- #include <gui/core/algo_factory.hpp>
- #include <gui/core/obj_convert.hpp>
- #include <gui/core/plugin_exception.hpp>
- #include <gui/core/plugin_factory.hpp>
- #include <gui/core/plugin_registry.hpp>
- #include <gui/core/plugin_utils.hpp>
- #include <gui/core/version.hpp>
- #include <gui/plugin/PluginCache.hpp>
- #include <gui/plugin/PluginInfo.hpp>
- #include <gui/plugin/PluginLibInfo.hpp>
- #include <gui/utils/message_box.hpp>
- #include <serial/objostr.hpp>
- #include <serial/objistr.hpp>
- #include <serial/serial.hpp>
- #include "plugin_handle_impl.hpp"
- #include <algorithm>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(objects);
- // typedef for our handle types (internal use only)
- typedef CRef<CPluginHandle_Impl> TPluginImpl;
- // functor for sorting plugin handles by content
- struct SPluginLessByClassName {
- bool operator() (const TPluginImpl& h0, const TPluginImpl& h1) const
- {
- return (h0->GetClassName() < h1->GetClassName());
- }
- };
- // functor for sorting plugin handles by menu name
- struct SPluginLessByMenuItem {
- bool operator()(const TPluginImpl& h1, const TPluginImpl& h2) const
- {
- // sort first by menu item
- if (h1->GetMenuItem() < h2->GetMenuItem()) {
- return true;
- }
- if (h1->GetMenuItem() > h2->GetMenuItem()) {
- return false;
- }
- // we always pass empty menu items - their sort order is unimportant
- if (h1->GetMenuItem().empty()) {
- return true;
- }
- // sort next by class name
- if (h1->GetClassName() < h2->GetClassName()) {
- return true;
- }
- if (h1->GetClassName() > h2->GetClassName()) {
- return false;
- }
- // sort finally by class name
- return (h1->GetCommand() < h2->GetCommand());
- }
- };
- typedef set<TPluginImpl, SPluginLessByMenuItem> TPluginRegistry;
- // our plugin registry
- static TPluginRegistry s_PluginRegistry;
- // mutex protecting access to the registry
- DEFINE_STATIC_MUTEX(s_PluginRegistryMutex);
- //
- // read the plugin cache in the specified directory and add its contents to the
- // current registry
- //
- void CPluginRegistry::InitPlugins(const string& path)
- {
- string cache_file(path + CDirEntry::GetPathSeparator() + "plugin-cache");
- {{
- // first, check to see if the plugin cache exists
- CFile file(cache_file);
- if ( !file.Exists() ) {
- LOG_POST(Info <<
- "CPluginRegistry::InitPlugins(): "
- "no plugin cache found at " << cache_file);
- return;
- }
- }}
- // try reading in ASN.1 text format
- try {
- auto_ptr<CObjectIStream> is
- (CObjectIStream::Open(eSerial_AsnText, cache_file));
- CRef<CPluginCache> cache(new CPluginCache());
- *is >> *cache;
- LOG_POST(Info
- << "CPluginRegistry::InitPlugins(): plugin cache found in "
- << path);
- x_InitPlugins(path, *cache);
- return;
- }
- catch (CException& _DEBUG_ARG(e)) {
- _TRACE("read of ASN.1 text plugin cache in "
- << path << " failed: " << e.what());
- }
- // on error, try reading in ASN.1 binary format
- try {
- auto_ptr<CObjectIStream> is
- (CObjectIStream::Open(eSerial_AsnBinary, cache_file));
- CRef<CPluginCache> cache(new CPluginCache());
- *is >> *cache;
- LOG_POST(Info
- << "CPluginRegistry::InitPlugins(): plugin cache found in "
- << path);
- x_InitPlugins(path, *cache);
- return;
- }
- catch (CException& _DEBUG_ARG(e)) {
- _TRACE("read of ASN.1 binary plugin cache in "
- << path << " failed: " << e.what());
- }
- // if not, try reading in XML
- try {
- auto_ptr<CObjectIStream> is
- (CObjectIStream::Open(eSerial_Xml, cache_file));
- CRef<CPluginCache> cache(new CPluginCache());
- *is >> *cache;
- LOG_POST(Info
- << "CPluginRegistry::InitPlugins(): plugin cache found in "
- << path);
- x_InitPlugins(path, *cache);
- return;
- }
- catch (CException& _DEBUG_ARG(e)) {
- _TRACE("read of XML plugin cache in "
- << path << " failed: " << e.what());
- }
- // log an error and continue...
- LOG_POST(Error
- << "CPluginRegistry: No plugins found in directory " << path);
- }
- void CPluginRegistry::x_InitPlugins(const string& path, CPluginCache& cache)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- //
- // now, process our plugin info objects
- //
- TPlugins plugins;
- int plug_count = s_PluginRegistry.size();
- NON_CONST_ITERATE (CPluginCache::Tdata, iter, cache.Set()) {
- CPluginLibInfo& libinfo = **iter;
- string lib_path = (path + CDirEntry::GetPathSeparator() +
- libinfo.GetLibrary());
- libinfo.SetLibrary(lib_path);
- CPluginHandle handle = AddPlugin(libinfo, eNonPersistent);
- plugins.push_back(handle);
- }
- //
- // ping any autoload commands now
- //
- NON_CONST_ITERATE (TPlugins, iter, plugins) {
- CPluginHandle handle = *iter;
- if ( !handle.GetInfo().CanGetAutorun() ||
- !handle.GetInfo().GetAutorun() ) {
- continue;
- }
- _TRACE("autoloading " << handle.GetInfo().GetClass_name());
- const CPluginInfo::TCommands& cmds =
- handle.GetInfo().GetCommands();
- try {
- switch (cmds.Which()) {
- case CPluginCommandSet::e_Algo:
- ITERATE (CPluginInfo::TCommands::TAlgo, cmd_iter,
- cmds.GetAlgo()) {
- CRef<CPluginMessage> msg(new CPluginMessage);
- CPluginRequest& request = msg->SetRequest();
- handle.FillDefaults
- ((EAlgoCommand)(*cmd_iter)->GetCommand(),
- request.SetAlgo());
- handle.Execute(*msg);
- }
- break;
- case CPluginCommandSet::e_View:
- break;
- case CPluginCommandSet::e_Data:
- break;
- default:
- break;
- }
- }
- catch (CException& e) {
- LOG_POST(Error << "Error running autoload commands: "
- << e.what());
- }
- #ifndef _DEBUG
- catch (...) {
- LOG_POST(Error << "Unknown error running autoload commands");
- }
- #endif
- }
- LOG_POST(Info << " registered "
- << s_PluginRegistry.size() - plug_count
- << " plugins in path " << path);
- }
- void CPluginRegistry::Clear(void)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- s_PluginRegistry.clear();
- }
- void CPluginRegistry::RegisterPlugin(CRef<CPluginInfo> info,
- CPluginFactoryBase *factory)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- // build a PluginLibInfo from info
- CRef<CPluginLibInfo> libinfo(new CPluginLibInfo);
- libinfo->SetInfo(*info);
- string lib_path = "NONE";
- libinfo->SetLibrary(lib_path);
- // make a plugin handle from this
- TPluginImpl handle(new CPluginHandle_Impl(*libinfo));
- // set the factory
- handle->x_SetFactory(factory);
- // register the plugin
- TPluginRegistry::iterator reg_iter = s_PluginRegistry.find(handle);
- if (reg_iter != s_PluginRegistry.end()) {
- LOG_POST(Warning
- << "Overriding "
- << libinfo->GetInfo().GetClass_name()
- << " with equivalent plugin from "
- << libinfo->GetLibrary());
- s_PluginRegistry.erase(reg_iter);
- }
- s_PluginRegistry.insert(handle);
- }
- CPluginHandle CPluginRegistry::AddPlugin(CPluginLibInfo& libinfo,
- EUserPlugin mode)
- {
- TPluginImpl impl(new CPluginHandle_Impl(libinfo));
- TPluginRegistry::iterator reg_iter = s_PluginRegistry.find(impl);
- if (reg_iter != s_PluginRegistry.end()) {
- LOG_POST(Warning
- << "Overriding "
- << libinfo.GetInfo().GetClass_name()
- << " with equivalent plugin from "
- << libinfo.GetLibrary());
- s_PluginRegistry.erase(reg_iter);
- }
- s_PluginRegistry.insert(impl);
- switch (mode) {
- case ePersistent:
- break;
- default:
- case eNonPersistent:
- break;
- }
- return impl->GetHandle();
- }
- template <class Command, class BufferObj>
- CPluginRegistry::TPlugins
- s_GetPlugins(const TPluginRegistry& registry, Command cmd,
- const BufferObj* obj, int flags)
- {
- // Some compilers (*cough*WorkShop*cough*) don't allow templates
- // to access statics, so we must use registry rather than
- // s_PluginRegistry here.
- CConvertCache cache;
- CPluginRegistry::TPlugins plugins;
- ITERATE (TPluginRegistry, iter, registry) {
- const CPluginHandle_Impl& handle = **iter;
- CPluginCommand args;
- if ( !handle.IsEnabled() ) {
- continue;
- }
- if ( (flags & CPluginRegistry::fHidden) == 0 &&
- handle.GetMenuItem().empty()) {
- continue;
- }
- if ( !handle.FillDefaults(cmd, args) ) {
- continue;
- }
- /**
- FIXME: this causes too many problems, and will be temporarily disabled
- it is *very* time-consuming on large records
- if (CPluginUtils::CanFitArgs(args.SetArgs(), *obj, &cache)) {
- plugins.push_back((*iter)->GetHandle());
- }
- **/
- plugins.push_back((*iter)->GetHandle());
- }
- return plugins;
- }
- //
- // retrieve plugins specific for a given command and valid for a given document
- //
- CPluginRegistry::TPlugins
- CPluginRegistry::GetPlugins(EAlgoCommand cmd, TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- return s_GetPlugins(s_PluginRegistry, cmd, (const IDocument*)NULL, flags);
- }
- CPluginRegistry::TPlugins
- CPluginRegistry::GetPlugins(EDataCommand cmd, const IDocument* doc,
- TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- return s_GetPlugins(s_PluginRegistry, cmd, doc, flags);
- }
- CPluginRegistry::TPlugins
- CPluginRegistry::GetPlugins(EViewCommand cmd, TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- return s_GetPlugins(s_PluginRegistry, cmd, (const IDocument*)NULL, flags);
- }
- //
- // retrieve plugins specific for a set of objects
- //
- CPluginRegistry::TPlugins
- CPluginRegistry::GetPlugins(EDataCommand cmd, const CSelectionBuffer& buf,
- TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- return s_GetPlugins(s_PluginRegistry, cmd, &buf, flags);
- }
- //
- // retrieve all plugins
- //
- CPluginHandle CPluginRegistry::GetPlugin(const string& name)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
- if ((*iter)->IsEnabled() && (*iter)->GetClassName() == name) {
- return (*iter)->GetHandle();
- }
- }
- _TRACE("CPluginRegistry::GetPlugin(): failed to find plugin " << name);
- return CPluginHandle();
- }
- //
- // retrieve all plugins
- //
- CPluginRegistry::TPlugins CPluginRegistry::GetPlugins(TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- TPlugins plugins;
- ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
- if ( (flags & fHidden) == 0 && (*iter)->GetMenuItem().empty()) {
- continue;
- }
- if ((*iter)->IsEnabled()) {
- plugins.push_back((*iter)->GetHandle());
- }
- }
- return plugins;
- }
- //
- // retrieve plugins valid for a given command type
- //
- CPluginRegistry::TPlugins
- CPluginRegistry::GetPlugins(CPluginCommandSet::E_Choice cmd, TFlags flags)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- TPlugins plugins;
- ITERATE (TPluginRegistry, iter, s_PluginRegistry) {
- if ( (flags & fHidden) == 0 && (*iter)->GetMenuItem().empty()) {
- continue;
- }
- if ( (*iter)->GetCommand() == cmd && (*iter)->IsEnabled()) {
- plugins.push_back((*iter)->GetHandle());
- }
- }
- return plugins;
- }
- void CPluginRegistry::x_LoadLibrary(const string& lib)
- {
- CMutexGuard LOCK(s_PluginRegistryMutex);
- string dir;
- string base;
- string ext;
- CDirEntry::SplitPath(lib, &dir, &base, &ext);
- CDll dll(dir, base + ext, CDll::eLoadLater);
- try {
- dll.Load();
- LOG_POST(Info << "loaded plugin library " << base + ext);
- // grab the single entry point
- list<CPluginFactoryBase*> plugins;
- CPluginFactoryBase::FPluginEntryPoint get_plugins =
- dll.GetEntryPoint_Func("NCBIGBenchGetPlugins", &get_plugins);
- if ( !get_plugins ) {
- NCBI_THROW(CPluginException, ePluginLoadFailed,
- "Library is not a valid plug-in");
- }
- // grab our plugin factories
- get_plugins(plugins);
- ITERATE (list<CPluginFactoryBase*>, iter, plugins) {
- CPluginFactoryBase* factory = *iter;
- if ( !factory ) {
- continue;
- }
- // check for version information
- //CPluginRequest request;
- //request.SetInfo();
- //CPluginReply reply;
- //factory->RunCommand(request, reply);
- //if ( reply.GetStatus() != eRequestStatus_success ||
- // !reply.GetAction().IsInfo() ) {
- // // the plugin factory doesn't support the 'info' command
- // continue;
- //}
- // make sure our library is set...
- CPluginInfo info;
- (*iter)->GetInfo(info);
- //const CPluginInfo& info = reply.GetAction().GetInfo();
- if ( !CPluginVersion::CheckVersion(info.GetVer_major(),
- info.GetVer_minor()) ) {
- string msg = "Version Mismatch:nframework version ";
- msg += NStr::IntToString(CPluginVersion::eMajor);
- msg += "." + NStr::IntToString(CPluginVersion::eMinor);
- msg += " : plugin version ";
- msg += NStr::IntToString(info.GetVer_major());
- msg += "." + NStr::IntToString(info.GetVer_minor());
- msg += ", rev " + NStr::IntToString(info.GetVer_revision());
- msg += "nplugin build date: " + info.GetVer_build_date();
- NCBI_THROW(CPluginException, eVersionMismatch, msg);
- }
- // retrieve and process all commands
- // we will fill in details for plugin handles as we go
- TPluginRegistry::iterator plug_iter = s_PluginRegistry.begin();
- for ( ; plug_iter != s_PluginRegistry.end(); ++plug_iter) {
- if ( (*plug_iter)->GetClassName() == info.GetClass_name() ) {
- (*plug_iter)->x_SetFactory(factory);
- LOG_POST(Info
- << "registering plugin " << info.GetClass_name());
- break;
- }
- }
- if (plug_iter == s_PluginRegistry.end()) {
- LOG_POST(Warning
- << "failed to register plugin "
- << (*plug_iter)->GetClassName());
- }
- }
- }
- catch(CException& e) {
- dll.Unload();
- string msg("Failed to load plugin library ");
- msg += base + ext;
- msg += ":n";
- msg += e.GetMsg();
- NcbiMessageBox(msg);
- }
- #ifndef _DEBUG
- catch (...) {
- dll.Unload();
- string msg("Failed to load plugin library ");
- msg += base + ext;
- msg += ":nUnknown error.";
- NcbiMessageBox(msg);
- }
- #endif
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: plugin_registry.cpp,v $
- * Revision 1000.8 2004/06/01 20:44:30 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.45
- *
- * Revision 1.45 2004/05/21 22:27:40 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.44 2004/04/16 14:38:28 dicuccio
- * Eliminated APIs from GetPlugins() that would perform selection-based sieving -
- * they were not used
- *
- * Revision 1.43 2004/03/16 15:59:50 vasilche
- * Removed warning about unused exception variable
- *
- * Revision 1.42 2004/01/27 18:32:10 dicuccio
- * Added default handler to switch
- *
- * Revision 1.41 2004/01/06 14:24:03 dicuccio
- * Temporarily disable the use of CanFitArgs() inside of GetPlugins() when all
- * that is known is a document - the search is very expensive on big records.
- *
- * Revision 1.40 2003/12/09 15:44:53 dicuccio
- * Use CException::GetMsg() instead of what()
- *
- * Revision 1.39 2003/12/03 12:40:05 dicuccio
- * Restore auto-processing of autorun plugins
- *
- * Revision 1.38 2003/11/26 17:06:56 dicuccio
- * Dropped autoloading of plugins - favor explicit initialization
- *
- * Revision 1.37 2003/11/24 15:39:40 dicuccio
- * Renamed CVersion to CPluginVersion
- *
- * Revision 1.36 2003/11/19 18:15:14 ucko
- * Adjust for CDll API change.
- *
- * Revision 1.35 2003/11/06 20:06:29 dicuccio
- * Moved USING_SCOPE(objects) to implementation files
- *
- * Revision 1.34 2003/11/04 17:19:07 dicuccio
- * Added Clear(). CHanged to patch API change in CPluginMessage
- *
- * Revision 1.33 2003/10/27 17:37:51 dicuccio
- * Better diagnostics for exceptions in reading plugin cache
- *
- * Revision 1.32 2003/10/25 16:03:37 dicuccio
- * Removed debugging output that disabled plugin reading on Unix
- *
- * Revision 1.31 2003/10/23 16:17:03 dicuccio
- * Added API to add user-defined plugins
- *
- * Revision 1.30 2003/10/10 17:15:33 dicuccio
- * Changed sort params for plugin handles - now, sort by menu item. Added object
- * conversion cache to plugin retrieval. Removed unnecessary sort()s.
- *
- * Revision 1.29 2003/09/30 23:48:04 ucko
- * s_GetPlugins: re-fixed WorkShop build, and added a comment explaining
- * how to stay out of trouble.
- *
- * Revision 1.28 2003/09/30 13:40:12 dicuccio
- * Added sorting of plugins by menu name
- *
- * Revision 1.27 2003/09/04 14:01:51 dicuccio
- * Introduce IDocument and IView as abstract base classes for CDocument and CView
- *
- * Revision 1.26 2003/08/05 17:07:15 dicuccio
- * Changed calling semantics for the message queue - pass by reference, not
- * CConstRef<>
- *
- * Revision 1.25 2003/07/28 18:27:38 jcherry
- * Added CPluginRegistry::RegisterPlugin for registering external
- * (executable) plugins
- *
- * Revision 1.24 2003/07/25 19:45:22 shomrat
- * Immediately execute autorun plugins
- *
- * Revision 1.23 2003/07/21 19:28:37 dicuccio
- * Added retrieval of plugins based on contents of a selection buffer
- *
- * Revision 1.22 2003/07/14 11:01:16 shomrat
- * Plugin messageing system related changes
- *
- * Revision 1.21 2003/07/09 12:29:21 dicuccio
- * (Finally!) fixed build issues on WorkShop - removed accessing of all static
- * variables from inside local templated functions
- *
- * Revision 1.20 2003/06/30 13:33:15 dicuccio
- * Added API to screen out "empty" plugins
- *
- * Revision 1.19 2003/06/30 11:29:34 dicuccio
- * Moved access of mutex out of template (WorkShop compiler doesn't like this)
- *
- * Revision 1.18 2003/06/29 13:10:17 dicuccio
- * Use DEFINE_STATIC_MUTEX() instead of static member variables
- *
- * Revision 1.17 2003/06/25 17:02:54 dicuccio
- * Split CPluginHandle into a handle (pointer-to-implementation) and
- * implementation file. Lots of #include file clean-ups.
- *
- * Revision 1.16 2003/06/20 14:47:41 dicuccio
- * Revised handling of plugin registration (moved GetInfo() out of plugin
- * factory and into each handler as a static function)
- *
- * Revision 1.15 2003/05/30 14:15:41 dicuccio
- * Renamed MessageBox to NcbiMessageBox because brain-dead MSVC thinks this is
- * ::MessageBox and rewrites the symbol as MessageBoxA, which results in an
- * unresolved external and conflict with the Win32 API :(.
- *
- * Revision 1.14 2003/05/30 12:56:50 dicuccio
- * Converted code to use MessageBox() instead of
- * fl_ask()/fl_message()/fl_alert()
- *
- * Revision 1.13 2003/05/19 13:35:59 dicuccio
- * Moved gui/core/plugin/ -> gui/plugin/. Merged gui/core/algo, gui/core/doc/,
- * and gui/core/view/ into one library (gui/core/)
- *
- * Revision 1.12 2003/05/08 16:18:59 dicuccio
- * Changed CFastMutex --> CMutex - guards against recursive locking
- *
- * Revision 1.11 2003/05/06 15:54:51 dicuccio
- * Added mutex to guard access to plugin registry
- *
- * Revision 1.10 2003/04/29 14:41:18 dicuccio
- * Removed old GetPlugins() call - use new command-based API
- *
- * Revision 1.9 2003/03/31 13:47:50 dicuccio
- * Changed standard start-up messages to be more comprehensible
- *
- * Revision 1.8 2003/03/25 13:11:10 dicuccio
- * Fixed compilation issue on compaq compiler - don't redeclare loop variable
- * 'iter' inside of loop
- *
- * Revision 1.7 2003/03/13 18:15:48 dicuccio
- * Added accessor for a single, named plugin. Changed registration to
- * explicitly allow overriding of plugins
- *
- * Revision 1.6 2003/03/10 22:58:51 kuznets
- * iterate -> ITERATE
- *
- * Revision 1.5 2003/02/28 15:06:55 dicuccio
- * Added check to see if a plugin is enabled
- *
- * Revision 1.4 2003/02/24 13:03:15 dicuccio
- * Renamed classes in plugin spec:
- * CArgSeg --> CPluginArgSet
- * CArgument --> CPluginArg
- * CPluginArgs --> CPluginCommand
- * CPluginCommands --> CPluginCommandSet
- *
- * Revision 1.3 2003/02/21 17:16:52 dicuccio
- * Fixed compilation errors related to changes in plugin architecture
- *
- * Revision 1.2 2003/02/20 20:35:45 dicuccio
- * Fixed compilation errors after commit of plugin architecture changes
- *
- * Revision 1.1 2003/02/20 19:49:56 dicuccio
- * Created new plugin architecture, based on ASN.1 spec. Moved GBENCH frameowrk
- * over to use new plugin architecture.
- *
- * ===========================================================================
- */