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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: scanner.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 20:49:09  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.29
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: scanner.cpp,v 1000.4 2004/06/01 20:49:09 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.  *    Command-line utility to scan a plugin directory and produce a plug-in
  38.  *    cache file
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbiapp.hpp>
  42. #include <corelib/ncbiargs.hpp>
  43. #include <corelib/ncbidll.hpp>
  44. #include <corelib/ncbienv.hpp>
  45. #include <corelib/ncbifile.hpp>
  46. #include <corelib/ncbireg.hpp>
  47. #include <gui/core/version.hpp>
  48. #include <gui/core/plugin_factory.hpp>
  49. #include <gui/plugin/PluginCache.hpp>
  50. #include <gui/plugin/PluginInfo.hpp>
  51. #include <serial/serial.hpp>
  52. #include <serial/objostrasnb.hpp>
  53. USING_NCBI_SCOPE;
  54. USING_SCOPE(objects);
  55. /////////////////////////////////////////////////////////////////////////////
  56. //  CScannerApp::
  57. class CScannerApp : public CNcbiApplication
  58. {
  59. public:
  60.     CScannerApp();
  61. private:
  62.     int m_Plugins;
  63.     virtual void Init(void);
  64.     virtual int  Run(void);
  65.     virtual void Exit(void);
  66. };
  67. CScannerApp::CScannerApp()
  68.     : m_Plugins(0)
  69. {
  70. }
  71. /////////////////////////////////////////////////////////////////////////////
  72. //  Init test for all different types of arguments
  73. void CScannerApp::Init(void)
  74. {
  75.     // Create command-line argument descriptions class
  76.     auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
  77.     // Specify USAGE context
  78.     arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
  79.                               "Plug-in cache maintenance program");
  80.     arg_desc->AddFlag("v", "Version");
  81.     arg_desc->AddFlag("strict", "Strict");
  82.     arg_desc->AddPositional("dir", "Directory to scan",
  83.                             CArgDescriptions::eString);
  84.     // Setup arg.descriptions for this application
  85.     SetupArgDescriptions(arg_desc.release());
  86. }
  87. /////////////////////////////////////////////////////////////////////////////
  88. //  Run test (printout arguments obtained from command-line)
  89. int CScannerApp::Run(void)
  90. {
  91.     // Get arguments
  92.     CArgs args = GetArgs();
  93.     if (args["v"]) {
  94.         cerr << "gbench_plugin_scan, version "
  95.             << CPluginVersion::eMajor << "." << CPluginVersion::eMinor << endl;
  96.         cerr << "build date: " << __DATE__ << " " << __TIME__ << endl;
  97.         return 0;
  98.     }
  99.     string dir_name   = args["dir"].AsString();
  100.     string cache_file = dir_name + "/plugin-cache";
  101.     bool strict = args["strict"];
  102.     CNcbiRegistry plugin_cache;
  103.     // okay, now we scan a directory and read it
  104.     // this is operating-system specific!
  105.     int libs_scanned = 0;
  106.     int plugins_registered = 0;
  107.     cout << "scanning plugin directory " << dir_name << "..." << endl;
  108.     CPluginCache cache;
  109.     CDir dir(dir_name);
  110.     if ( !dir.Exists() ) {
  111.         cout << "  directory " << dir_name << " does not exist" << endl;
  112.         return 1;
  113.     }
  114.     CDir::TMode mode;
  115.     dir.GetMode(&mode);
  116.     if ( !(mode & CDir::fWrite) ) {
  117.         cout << "  cannot update cache in directory " << dir_name
  118.             << ": directory is not writeable" << endl;
  119.         return 1;
  120.     }
  121.     CDir::TEntries entries = dir.GetEntries("*");
  122.     ITERATE (CDir::TEntries, entry_iter, entries) {
  123.         if ( !(*entry_iter)->IsFile() ) {
  124.             continue;
  125.         }
  126.         string full_path = (*entry_iter)->GetPath();
  127.         string path      = (*entry_iter)->GetDir();
  128.         string file      = (*entry_iter)->GetName();
  129.         // screen for platform-specific libraries
  130. #ifdef NCBI_OS_MSWIN
  131.         // Winders: must be name.dll
  132.         if (file.find(".dll") != file.length() - 4) {
  133.             continue;
  134.         }
  135. #elif defined(NCBI_OS_UNIX)  ||  defined(NCBI_OS_LINUX)
  136.         // Unix / MacOS X: must be libname.so
  137.         if (file.find(".so") != file.length() - 3  ||
  138.             file.find("lib") != 0) {
  139.             continue;
  140.         }
  141. #endif
  142.         // given that we have a library, see if this library corresponds to our
  143.         // criteria for a plug-in
  144.         try {
  145.             LOG_POST(Info << "evaluating " << file << "...");
  146.             // ideally, we should load our plugin and unload it after we're
  147.             // done registering our plugins.  practically, on some compilers,
  148.             // this presents some seriously nasty issues regarding
  149.             // initialization of statics - static a living in this app is
  150.             // initialized by this app, then initialized again by the plugin.
  151.             // When the plugin exits, it doesn't get de-initialized, but the
  152.             // reference living in the static is to a piece of invalid memory.
  153.             // This occurs only when genome workbench is linked against static
  154.             // libraries, and does appear to be somewhat platform specific
  155. #if defined (NCBI_COMPILER_WORKSHOP)  ||  defined(NCBI_OS_OSF1)  ||  defined(NCBI_COMPILER_METROWERKS)  ||  defined(NCBI_OS_DARWIN)
  156.             CDll dll(path, file, CDll::eLoadNow);
  157. #else
  158.             CDll dll(path, file, CDll::eLoadNow, CDll::eAutoUnload);
  159. #endif
  160.             CPluginFactoryBase::FPluginEntryPoint get_plugins;
  161.             get_plugins = dll.GetEntryPoint_Func("NCBIGBenchGetPlugins",
  162.                                                  &get_plugins);
  163.             if ( !get_plugins ) {
  164.                 LOG_POST(Info
  165.                          << "rejecting " << file << ": no plugin entry point");
  166.                 continue;
  167.             }
  168.             list<CPluginFactoryBase*> plugins;
  169.             get_plugins(plugins);
  170.             cout << "  scanning plugin library " << file << "..." << endl;
  171.             ++libs_scanned;
  172.             ITERATE(list<CPluginFactoryBase*>, plug_iter, plugins) {
  173.                 CRef<CPluginInfo> info(new CPluginInfo);
  174.                 (*plug_iter)->GetInfo(*info);
  175.                 if ( !CPluginVersion::CheckVersion(info->GetVer_major(),
  176.                                              info->GetVer_minor()) ) {
  177.                     LOG_POST(Warning
  178.                              << "rejecting plugin library " << file
  179.                              << ": version mismatch");
  180.                     LOG_POST(Warning
  181.                              << "  (framework version: "
  182.                              << (int)CPluginVersion::eMajor << "."
  183.                              << (int)CPluginVersion::eMinor << ", "
  184.                              << "plugin version: "
  185.                              << info->GetVer_major() << "."
  186.                              << info->GetVer_minor() << ")");
  187.                     LOG_POST(Warning
  188.                              << "  (plugin revision: "
  189.                              << info->GetVer_revision() << ", "
  190.                              << "plugin build date: "
  191.                              << info->GetVer_build_date());
  192.                 }
  193.                 cache.AddPlugin(file, *info);
  194.                 cout << "    registering plugin "
  195.                     << info->GetClass_name() << endl;
  196.                 ++plugins_registered;
  197.             }
  198.         }
  199.         catch (CException& e) {
  200.             cout << "  error loading " << file << ": " << e.GetMsg() << endl;
  201.             if (strict) {
  202.                 throw;
  203.             }
  204.         }
  205.         catch (...) {
  206.             cout << "  error loading " << file << endl;
  207.             if (strict) {
  208.                 throw;
  209.             }
  210.         }
  211.     }
  212.     cout << "  writing plugin cache..." << endl;
  213.     try {
  214.         auto_ptr<CObjectOStream> os(CObjectOStream::Open(eSerial_AsnText,
  215.                                                          cache_file));
  216.         *os << cache;
  217.     }
  218.     catch (CException& e) {
  219.         LOG_POST(Error << "failed to write cache: " << e.GetMsg());
  220.         return 1;
  221.     }
  222.     catch (exception& e) {
  223.         LOG_POST(Error << "failed to write cache: " << e.what());
  224.         return 1;
  225.     }
  226.     catch (...) {
  227.         LOG_POST(Error << "failed to write cache: unknown error");
  228.         return 1;
  229.     }
  230.     cout << "  done.  " << libs_scanned;
  231.     if (libs_scanned != 1) {
  232.         cout << " libraries scanned, ";
  233.     } else {
  234.         cout << " library scanned, ";
  235.     }
  236.     cout << plugins_registered;
  237.     if (plugins_registered != 1) {
  238.         cout << " plugins registered." << endl;
  239.     } else {
  240.         cout << " plugin registered." << endl;
  241.     }
  242.     return 0;
  243. }
  244. /////////////////////////////////////////////////////////////////////////////
  245. //  Cleanup
  246. void CScannerApp::Exit(void)
  247. {
  248.     SetDiagStream(0);
  249. }
  250. /////////////////////////////////////////////////////////////////////////////
  251. //  MAIN
  252. int main(int argc, const char* argv[])
  253. {
  254.     // Execute main application function
  255.     return CScannerApp().AppMain(argc, argv, 0, eDS_Default, 0);
  256. }
  257. /*
  258.  * ===========================================================================
  259.  * $Log: scanner.cpp,v $
  260.  * Revision 1000.4  2004/06/01 20:49:09  gouriano
  261.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.29
  262.  *
  263.  * Revision 1.29  2004/05/21 22:27:42  gorelenk
  264.  * Added PCH ncbi_pch.hpp
  265.  *
  266.  * Revision 1.28  2004/05/12 22:01:02  ucko
  267.  * Don't attempt to unload plugins on Darwin.
  268.  *
  269.  * Revision 1.27  2004/03/30 20:09:09  dicuccio
  270.  * Added try/catch around writing of plugin cache to deal with errors more
  271.  * gracefully
  272.  *
  273.  * Revision 1.26  2003/12/09 15:45:51  dicuccio
  274.  * Use CException::GetMsg() instead of what()
  275.  *
  276.  * Revision 1.25  2003/11/24 15:42:03  dicuccio
  277.  * Renamed CVersion to CPluginVersion
  278.  *
  279.  * Revision 1.24  2003/11/19 18:15:27  ucko
  280.  * Adjust for CDll API change.
  281.  *
  282.  * Revision 1.23  2003/11/06 20:09:47  dicuccio
  283.  * Added USING_SCOPE(objects) to implemnentation files
  284.  *
  285.  * Revision 1.22  2003/09/29 15:43:01  dicuccio
  286.  * Deprecated gui/scope.hpp.  Merged gui/core/types.hpp into gui/types.hpp
  287.  *
  288.  * Revision 1.21  2003/07/19 00:43:44  dicuccio
  289.  * Added optional flag for strict error processing: strict error processing will
  290.  * not silently ignore unresolved externals from plugins, it will throw and exit
  291.  *
  292.  * Revision 1.20  2003/07/14 11:22:20  shomrat
  293.  * Plugin messageing system related changes
  294.  *
  295.  * Revision 1.19  2003/06/20 14:48:38  dicuccio
  296.  * Changed CPluginFactory --> CPluginFactoryBase
  297.  *
  298.  * Revision 1.18  2003/06/18 13:51:25  rsmith
  299.  * Mac Codewarrior should not do auto unloads either.
  300.  *
  301.  * Revision 1.17  2003/05/19 13:37:28  dicuccio
  302.  * Moved gui/core/plugin/ -> gui/plugin/
  303.  *
  304.  * Revision 1.16  2003/04/07 14:46:14  ucko
  305.  * OSF/1 fares no better with the native compiler, so always delay
  306.  * unloading on that OS.
  307.  *
  308.  * Revision 1.15  2003/03/31 18:45:15  dicuccio
  309.  * Added obtuse platform-specific work-around:  When loading dlls explicitly, it
  310.  * is possible that the dll will re-initialize a static variable in the app.
  311.  * Such variables are left in an undefined state when the explicitly loaded dll
  312.  * is explicitly unloaded.  So we simply don't explicitly unload the dlls we've
  313.  * loaded.
  314.  *
  315.  * Revision 1.14  2003/03/11 15:18:57  kuznets
  316.  * iterate -> ITERATE
  317.  *
  318.  * Revision 1.13  2003/03/07 17:33:36  dicuccio
  319.  * Don't scan directories that are not writeable
  320.  *
  321.  * Revision 1.12  2003/02/26 20:57:00  dicuccio
  322.  * Added cast for enum -> int (Solaris compilation error)
  323.  *
  324.  * Revision 1.11  2003/02/26 19:24:14  dicuccio
  325.  * Minor output formatting changes
  326.  *
  327.  * Revision 1.10  2003/02/20 19:50:47  dicuccio
  328.  * Created new plugin architecture, based on ASN.1 spec.  Moved GBENCH framework
  329.  * over to use new architecture.
  330.  *
  331.  * Revision 1.9  2003/01/13 13:10:11  dicuccio
  332.  * Namespace clean-up.  Retired namespace gui -> converted all to namespace
  333.  * ncbi.  Moved all FLUID-generated code into namespace ncbi.
  334.  *
  335.  * Revision 1.8  2003/01/08 15:02:54  dicuccio
  336.  * Updated to match changes in type specification system
  337.  *
  338.  * Revision 1.7  2003/01/03 20:39:13  dicuccio
  339.  * Changed '-version' command line parameter to '-v'
  340.  *
  341.  * Revision 1.6  2002/12/23 14:12:30  dicuccio
  342.  * added new command line option to return the version of the binaries
  343.  *
  344.  * Revision 1.5  2002/11/29 16:14:40  dicuccio
  345.  * Minor change - use direct function pointer call insteadl of dereferencing
  346.  *
  347.  * Revision 1.4  2002/11/25 21:02:15  dicuccio
  348.  * Moved typedefs to class-scope instead of function scope.
  349.  * Added templatized plugin processing function - avoids duplicate
  350.  * functionality.  Added scanning for data loader plugins.  Changed stored
  351.  * library names to reflect local names instead of full path names.
  352.  *
  353.  * Revision 1.3  2002/11/14 16:23:53  dicuccio
  354.  * Fixed registration of single class for multiple types.
  355.  *
  356.  * Revision 1.2  2002/11/07 18:56:14  dicuccio
  357.  * Minor style changes (use typedef FFooFunc instead of typedef TFooFunc)
  358.  *
  359.  * Revision 1.1  2002/11/06 18:29:26  dicuccio
  360.  * Initial revision
  361.  *
  362.  * ===========================================================================
  363.  */