vtkPVPluginLoader.cxx 21.1 KB
Newer Older
1 2 3
/*=========================================================================

  Program:   ParaView
4
  Module:    vtkPVPluginLoader.cxx
5 6 7 8 9 10 11 12 13 14

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
#include "vtkPVPluginLoader.h"
16 17

#include "vtkDynamicLoader.h"
18
#include "vtkNew.h"
19
#include "vtkObjectFactory.h"
20
#include "vtkPDirectory.h"
21
#include "vtkPVConfig.h"
22
#include "vtkPVOptions.h"
23
#include "vtkPVPlugin.h"
24
#include "vtkPVPluginTracker.h"
25
#include "vtkPVPythonPluginInterface.h"
26
#include "vtkPVServerManagerPluginInterface.h"
27
#include "vtkPVXMLParser.h"
28
#include "vtkProcessModule.h"
29

30
#include <sstream>
31
#include <string>
32
#include <vtksys/SystemTools.hxx>
33

34
#include <cstdlib>
35

Kitware Robot's avatar
Kitware Robot committed
36 37 38 39 40 41 42 43 44 45 46 47 48
#define vtkPVPluginLoaderDebugMacro(x)                                                             \
  {                                                                                                \
    if (this->DebugPlugin)                                                                         \
    {                                                                                              \
      std::ostringstream vtkerror;                                                                 \
      vtkerror << x;                                                                               \
      vtkOutputWindowDisplayText(vtkerror.str().c_str());                                          \
    }                                                                                              \
  }

#define vtkPVPluginLoaderErrorMacro(x)                                                             \
  if (!no_errors)                                                                                  \
  {                                                                                                \
49
    vtkErrorMacro(<< x << endl);                                                                   \
Kitware Robot's avatar
Kitware Robot committed
50 51
  }                                                                                                \
  this->SetErrorString(x);
52

53
#if defined(_WIN32) && !defined(__CYGWIN__)
Kitware Robot's avatar
Kitware Robot committed
54
const char ENV_PATH_SEP = ';';
55
#else
Kitware Robot's avatar
Kitware Robot committed
56
const char ENV_PATH_SEP = ':';
57 58
#endif

59 60
namespace
{
Kitware Robot's avatar
Kitware Robot committed
61 62 63
// This is an helper class used for plugins constructed from XMLs.
class vtkPVXMLOnlyPlugin : public vtkPVPlugin, public vtkPVServerManagerPluginInterface
{
64 65
  std::string PluginName;
  std::string XML;
66 67 68
  vtkPVXMLOnlyPlugin(){};
  vtkPVXMLOnlyPlugin(const vtkPVXMLOnlyPlugin& other);
  void operator=(const vtkPVXMLOnlyPlugin& other);
Kitware Robot's avatar
Kitware Robot committed
69

70 71
public:
  static vtkPVXMLOnlyPlugin* Create(const char* xmlfile)
Kitware Robot's avatar
Kitware Robot committed
72
  {
73 74 75
    vtkNew<vtkPVXMLParser> parser;
    parser->SetFileName(xmlfile);
    if (!parser->Parse())
Kitware Robot's avatar
Kitware Robot committed
76
    {
77
      return NULL;
Kitware Robot's avatar
Kitware Robot committed
78
    }
79 80

    vtkPVXMLOnlyPlugin* instance = new vtkPVXMLOnlyPlugin();
Kitware Robot's avatar
Kitware Robot committed
81
    instance->PluginName = vtksys::SystemTools::GetFilenameWithoutExtension(xmlfile);
82 83 84 85

    ifstream is;
    is.open(xmlfile, ios::binary);
    // get length of file:
Kitware Robot's avatar
Kitware Robot committed
86
    is.seekg(0, ios::end);
87
    size_t length = is.tellg();
Kitware Robot's avatar
Kitware Robot committed
88
    is.seekg(0, ios::beg);
89 90

    // allocate memory:
Kitware Robot's avatar
Kitware Robot committed
91
    char* buffer = new char[length + 1];
92 93

    // read data as a block:
Kitware Robot's avatar
Kitware Robot committed
94
    is.read(buffer, length);
95 96 97
    is.close();
    buffer[length] = 0;
    instance->XML = buffer;
Kitware Robot's avatar
Kitware Robot committed
98
    delete[] buffer;
99
    return instance;
Kitware Robot's avatar
Kitware Robot committed
100
  }
101 102 103

  // Description:
  // Returns the name for this plugin.
104
  const char* GetPluginName() override { return this->PluginName.c_str(); }
105 106 107

  // Description:
  // Returns the version for this plugin.
108
  const char* GetPluginVersionString() override { return "1.0"; }
109 110 111

  // Description:
  // Returns true if this plugin is required on the server.
112
  bool GetRequiredOnServer() override { return true; }
113 114 115

  // Description:
  // Returns true if this plugin is required on the client.
116
  bool GetRequiredOnClient() override { return false; }
117 118 119

  // Description:
  // Returns a ';' separated list of plugin names required by this plugin.
120
  const char* GetRequiredPlugins() override { return ""; }
121 122 123

  // Description:
  // Obtain the server-manager configuration xmls, if any.
124
  void GetXMLs(std::vector<std::string>& xmls) override { xmls.push_back(this->XML); }
125 126 127 128 129

  // Description:
  // Returns the callback function to call to initialize the interpretor for the
  // new vtk/server-manager classes added by this plugin. Returning NULL is
  // perfectly valid.
130 131
  vtkClientServerInterpreterInitializer::InterpreterInitializationCallback
  GetInitializeInterpreterCallback() override
Kitware Robot's avatar
Kitware Robot committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
  {
    return NULL;
  }
};

// Cleans successfully opened libs when the application quits.
// BUG # 10293
class vtkPVPluginLoaderCleaner
{
  typedef std::map<std::string, vtkLibHandle> HandlesType;
  HandlesType Handles;
  std::vector<vtkPVXMLOnlyPlugin*> XMLPlugins;

public:
  void Register(const char* pname, vtkLibHandle& handle) { this->Handles[pname] = handle; }
  void Register(vtkPVXMLOnlyPlugin* plugin) { this->XMLPlugins.push_back(plugin); }
148

Kitware Robot's avatar
Kitware Robot committed
149 150 151 152
  ~vtkPVPluginLoaderCleaner()
  {
    for (HandlesType::const_iterator iter = this->Handles.begin(); iter != this->Handles.end();
         ++iter)
153
    {
Kitware Robot's avatar
Kitware Robot committed
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
      vtkDynamicLoader::CloseLibrary(iter->second);
    }
    for (std::vector<vtkPVXMLOnlyPlugin*>::iterator iter = this->XMLPlugins.begin();
         iter != this->XMLPlugins.end(); ++iter)
    {
      delete *iter;
    }
  }
  static vtkPVPluginLoaderCleaner* GetInstance()
  {
    if (!vtkPVPluginLoaderCleaner::LibCleaner)
    {
      vtkPVPluginLoaderCleaner::LibCleaner = new vtkPVPluginLoaderCleaner();
    }
    return vtkPVPluginLoaderCleaner::LibCleaner;
  }
  static void FinalizeInstance()
  {
    if (vtkPVPluginLoaderCleaner::LibCleaner)
    {
      vtkPVPluginLoaderCleaner* cleaner = vtkPVPluginLoaderCleaner::LibCleaner;
      vtkPVPluginLoaderCleaner::LibCleaner = NULL;
      delete cleaner;
    }
  }
  static void PluginLibraryUnloaded(const char* pname)
  {
    if (vtkPVPluginLoaderCleaner::LibCleaner && pname)
    {
      vtkPVPluginLoaderCleaner::LibCleaner->Handles.erase(pname);
    }
  }
186

Kitware Robot's avatar
Kitware Robot committed
187 188 189 190
private:
  static vtkPVPluginLoaderCleaner* LibCleaner;
};
vtkPVPluginLoaderCleaner* vtkPVPluginLoaderCleaner::LibCleaner = NULL;
191
};
192

193 194 195 196 197 198 199 200 201 202
//=============================================================================
static int nifty_counter = 0;
vtkPVPluginLoaderCleanerInitializer::vtkPVPluginLoaderCleanerInitializer()
{
  nifty_counter++;
}
vtkPVPluginLoaderCleanerInitializer::~vtkPVPluginLoaderCleanerInitializer()
{
  nifty_counter--;
  if (nifty_counter == 0)
Kitware Robot's avatar
Kitware Robot committed
203
  {
204
    vtkPVPluginLoaderCleaner::FinalizeInstance();
Kitware Robot's avatar
Kitware Robot committed
205
  }
206 207 208
}
//=============================================================================

209 210
vtkPluginLoadFunction vtkPVPluginLoader::StaticPluginLoadFunction = 0;

211
vtkStandardNewMacro(vtkPVPluginLoader);
212
//-----------------------------------------------------------------------------
213
vtkPVPluginLoader::vtkPVPluginLoader()
214
{
215
  this->DebugPlugin = vtksys::SystemTools::GetEnv("PV_PLUGIN_DEBUG") != NULL;
216 217 218 219 220 221 222
  this->ErrorString = NULL;
  this->PluginName = NULL;
  this->PluginVersion = NULL;
  this->FileName = NULL;
  this->SearchPaths = NULL;
  this->Loaded = false;
  this->SetErrorString("No plugin loaded yet.");
223 224 225

  vtksys::String paths;
  const char* env = vtksys::SystemTools::GetEnv("PV_PLUGIN_PATH");
Kitware Robot's avatar
Kitware Robot committed
226 227
  if (env)
  {
228
    paths += env;
229
    vtkPVPluginLoaderDebugMacro("PV_PLUGIN_PATH: " << env);
Kitware Robot's avatar
Kitware Robot committed
230
  }
231

232
#ifdef PARAVIEW_PLUGIN_LOADER_PATHS
Kitware Robot's avatar
Kitware Robot committed
233 234
  if (!paths.empty())
  {
235
    paths += ENV_PATH_SEP;
Kitware Robot's avatar
Kitware Robot committed
236
  }
237 238 239
  paths += PARAVIEW_PLUGIN_LOADER_PATHS;
#endif

240
  vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
Clinton Stimpson's avatar
Clinton Stimpson committed
241
  vtkPVOptions* opt = pm ? pm->GetOptions() : NULL;
Kitware Robot's avatar
Kitware Robot committed
242 243
  if (opt)
  {
244
    std::string appDir = vtkProcessModule::GetProcessModule()->GetSelfDir();
Kitware Robot's avatar
Kitware Robot committed
245 246
    if (appDir.size())
    {
Clinton Stimpson's avatar
Clinton Stimpson committed
247
      appDir += "/plugins";
Kitware Robot's avatar
Kitware Robot committed
248 249
      if (paths.size())
      {
250
        paths += ENV_PATH_SEP;
Clinton Stimpson's avatar
Clinton Stimpson committed
251
      }
Kitware Robot's avatar
Kitware Robot committed
252 253
      paths += appDir;
    }
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
254

Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
255 256 257
    // pqPluginManager::pluginPaths() used to automatically load plugins a host
    // of locations. We no longer support that. It becomes less useful since we
    // now list plugins in the plugin manager dialog.
Kitware Robot's avatar
Kitware Robot committed
258
  }
259

260
  this->SetSearchPaths(paths.c_str());
261 262 263
}

//-----------------------------------------------------------------------------
264
vtkPVPluginLoader::~vtkPVPluginLoader()
265
{
266 267 268 269 270
  this->SetErrorString(0);
  this->SetPluginName(0);
  this->SetPluginVersion(0);
  this->SetFileName(0);
  this->SetSearchPaths(0);
271 272 273
}

//-----------------------------------------------------------------------------
274 275
void vtkPVPluginLoader::LoadPluginsFromPluginSearchPath()
{
276
#ifdef BUILD_SHARED_LIBS
277 278
  vtkPVPluginLoaderDebugMacro("Loading Plugins from standard PLUGIN_PATHS \n"
    << this->SearchPaths << endl);
279

280
  std::vector<std::string> paths;
281 282
  vtksys::SystemTools::Split(this->SearchPaths, paths, ENV_PATH_SEP);
  for (size_t cc = 0; cc < paths.size(); cc++)
Kitware Robot's avatar
Kitware Robot committed
283
  {
284
    std::vector<std::string> subpaths;
285
    vtksys::SystemTools::Split(paths[cc], subpaths, ';');
286
    for (size_t scc = 0; scc < subpaths.size(); scc++)
Kitware Robot's avatar
Kitware Robot committed
287
    {
288
      this->LoadPluginsFromPath(subpaths[scc].c_str());
289
    }
Kitware Robot's avatar
Kitware Robot committed
290
  }
291
#else
292
  vtkPVPluginLoaderDebugMacro("Static build. Skipping PLUGIN_PATHS.\n");
293
#endif
294 295
}

296 297 298 299 300 301
//-----------------------------------------------------------------------------
void vtkPVPluginLoader::LoadPluginsFromPluginConfigFile()
{
#ifdef BUILD_SHARED_LIBS
  const char* configFiles = vtksys::SystemTools::GetEnv("PV_PLUGIN_CONFIG_FILE");
  if (configFiles != NULL)
Kitware Robot's avatar
Kitware Robot committed
302 303
  {
    vtkPVPluginLoaderDebugMacro("Loading Plugins from standard PV_PLUGIN_CONFIG_FILE \n"
304 305 306 307 308
      << configFiles);

    std::vector<std::string> paths;
    vtksys::SystemTools::Split(configFiles, paths, ENV_PATH_SEP);
    for (size_t cc = 0; cc < paths.size(); cc++)
Kitware Robot's avatar
Kitware Robot committed
309
    {
310
      std::vector<std::string> subpaths;
311
      vtksys::SystemTools::Split(paths[cc], subpaths, ';');
312
      for (size_t scc = 0; scc < subpaths.size(); scc++)
Kitware Robot's avatar
Kitware Robot committed
313 314
      {
        vtkPVPluginTracker::GetInstance()->LoadPluginConfigurationXML(subpaths[scc].c_str(), true);
315 316
      }
    }
Kitware Robot's avatar
Kitware Robot committed
317
  }
318
#else
319
  vtkPVPluginLoaderDebugMacro("Static build. Skipping PV_PLUGIN_CONFIG_FILE.\n");
320 321
#endif
}
322 323 324
//-----------------------------------------------------------------------------
void vtkPVPluginLoader::LoadPluginsFromPath(const char* path)
{
325
  vtkPVPluginLoaderDebugMacro("Loading plugins in Path: " << path << endl);
326 327
  vtkNew<vtkPDirectory> dir;
  if (dir->Load(path) == false)
Kitware Robot's avatar
Kitware Robot committed
328
  {
329
    vtkPVPluginLoaderDebugMacro("Invalid directory: " << path << endl);
330
    return;
Kitware Robot's avatar
Kitware Robot committed
331
  }
332

Kitware Robot's avatar
Kitware Robot committed
333 334 335 336
  for (vtkIdType cc = 0; cc < dir->GetNumberOfFiles(); cc++)
  {
    std::string ext = vtksys::SystemTools::GetFilenameLastExtension(dir->GetFile(cc));
    if (ext == ".so" || ext == ".dll" || ext == ".xml" || ext == ".dylib" || ext == ".sl")
337
    {
338
      std::string file = dir->GetPath();
339
      file += "/";
340
      file += dir->GetFile(cc);
341 342
      this->LoadPluginSilently(file.c_str());
    }
Kitware Robot's avatar
Kitware Robot committed
343
  }
344 345 346 347
}

//-----------------------------------------------------------------------------
bool vtkPVPluginLoader::LoadPluginInternal(const char* file, bool no_errors)
348
{
349
  this->Loaded = false;
Kitware Robot's avatar
Kitware Robot committed
350 351
  vtkPVPluginLoaderDebugMacro("\n***************************************************\n"
                              "Attempting to load "
352
    << file << endl);
353
  if (!file || file[0] == '\0')
Kitware Robot's avatar
Kitware Robot committed
354
  {
355
    vtkPVPluginLoaderErrorMacro("Invalid filename");
356
    return false;
Kitware Robot's avatar
Kitware Robot committed
357
  }
358

359
  this->SetFileName(file);
360
  std::string defaultname = vtksys::SystemTools::GetFilenameWithoutExtension(file);
361
  this->SetPluginName(defaultname.c_str());
362 363

  if (vtksys::SystemTools::GetFilenameLastExtension(file) == ".xml")
Kitware Robot's avatar
Kitware Robot committed
364
  {
365
    vtkPVPluginLoaderDebugMacro("Loading XML plugin" << endl);
366 367
    vtkPVXMLOnlyPlugin* plugin = vtkPVXMLOnlyPlugin::Create(file);
    if (plugin)
Kitware Robot's avatar
Kitware Robot committed
368
    {
369
      vtkPVPluginLoaderCleaner::GetInstance()->Register(plugin);
370
      return this->LoadPlugin(file, plugin);
Kitware Robot's avatar
Kitware Robot committed
371
    }
372 373 374
    vtkPVPluginLoaderErrorMacro(
      "Failed to load XML plugin. Not a valid XML or file could not be read.");
    return false;
Kitware Robot's avatar
Kitware Robot committed
375
  }
376
#ifndef BUILD_SHARED_LIBS
Kitware Robot's avatar
Kitware Robot committed
377 378
  if (StaticPluginLoadFunction && StaticPluginLoadFunction(file))
  {
379 380
    this->Loaded = true;
    return true;
Kitware Robot's avatar
Kitware Robot committed
381 382 383
  }
  vtkPVPluginLoaderErrorMacro("Could not find the plugin statically linked in, and "
                              "cannot load dynamic plugins  in static builds.");
384 385
  return false;
#else // ifndef BUILD_SHARED_LIBS
386 387
  vtkLibHandle lib = vtkDynamicLoader::OpenLibrary(file);
  if (!lib)
Kitware Robot's avatar
Kitware Robot committed
388
  {
389
    vtkPVPluginLoaderErrorMacro(vtkDynamicLoader::LastError());
390 391
    vtkPVPluginLoaderDebugMacro("Failed to load the shared library." << endl);
    vtkPVPluginLoaderDebugMacro(this->ErrorString << endl);
392
    return false;
Kitware Robot's avatar
Kitware Robot committed
393
  }
394 395

  vtkPVPluginLoaderDebugMacro("Loaded shared library successfully. "
396 397
                              "Now trying to validate that it's a ParaView plugin."
    << endl);
398 399 400 401 402

  // A plugin shared library has two global functions:
  // * pv_plugin_query_verification_data -- to obtain version
  // * pv_plugin_instance -- to obtain the plugin instance.

403
  pv_plugin_query_verification_data_fptr pv_plugin_query_verification_data =
404
    (pv_plugin_query_verification_data_fptr)(
Kitware Robot's avatar
Kitware Robot committed
405
      vtkDynamicLoader::GetSymbolAddress(lib, "pv_plugin_query_verification_data"));
406
  if (!pv_plugin_query_verification_data)
Kitware Robot's avatar
Kitware Robot committed
407 408 409
  {
    vtkPVPluginLoaderDebugMacro(
      "Failed to locate the global function "
410 411
      "\"pv_plugin_query_verification_data\" which is required to test the "
      "plugin signature. This may not be a ParaView plugin dll or maybe "
412 413
      "from a older version of ParaView when this function was not required."
      << endl);
414
    vtkPVPluginLoaderErrorMacro(
415 416
      "Not a ParaView Plugin since could not locate the plugin-verification function");
    vtkDynamicLoader::CloseLibrary(lib);
417
    return false;
Kitware Robot's avatar
Kitware Robot committed
418
  }
419

420
  std::string pv_verfication_data = pv_plugin_query_verification_data();
421

422
  vtkPVPluginLoaderDebugMacro("Plugin's signature: " << pv_verfication_data << endl);
423 424 425

  // Validate the signature. If the signature is invalid, then this plugin is
  // totally bogus (even for the GUI layer).
426
  if (pv_verfication_data != _PV_PLUGIN_VERIFICATION_STRING)
Kitware Robot's avatar
Kitware Robot committed
427
  {
428
    std::ostringstream error;
Kitware Robot's avatar
Kitware Robot committed
429 430 431
    error << "Mismatch in versions: \n"
          << "ParaView Signature: " << _PV_PLUGIN_VERIFICATION_STRING << "\n"
                                                                         "Plugin Signature: "
432
          << pv_verfication_data;
433
    vtkPVPluginLoaderErrorMacro(error.str().c_str());
434
    vtkDynamicLoader::CloseLibrary(lib);
Kitware Robot's avatar
Kitware Robot committed
435 436
    vtkPVPluginLoaderDebugMacro("Mismatch in versions signifies that the plugin was built for "
                                "a different version of ParaView or with a different compilter. "
437 438
                                "Look at the signatures to determine what caused the mismatch."
      << endl);
439
    return false;
Kitware Robot's avatar
Kitware Robot committed
440
  }
441 442 443

  // If we succeeded so far, then obtain the instace of vtkPVPlugin for this
  // plugin and load it.
444 445

  pv_plugin_query_instance_fptr pv_plugin_query_instance =
Kitware Robot's avatar
Kitware Robot committed
446
    (pv_plugin_query_instance_fptr)(vtkDynamicLoader::GetSymbolAddress(lib, "pv_plugin_instance"));
447
  if (!pv_plugin_query_instance)
Kitware Robot's avatar
Kitware Robot committed
448 449 450
  {
    vtkPVPluginLoaderDebugMacro(
      "We've encountered an error locating the other "
451 452
      "global function \"pv_plugin_instance\" which is required to locate the "
      "instance of the vtkPVPlugin class. Possibly the plugin shared library was "
453 454
      "not compiled properly."
      << endl);
Kitware Robot's avatar
Kitware Robot committed
455 456
    vtkPVPluginLoaderErrorMacro("Not a ParaView Plugin since could not locate the plugin-instance "
                                "function.");
457
    vtkDynamicLoader::CloseLibrary(lib);
458
    return false;
Kitware Robot's avatar
Kitware Robot committed
459
  }
460

Kitware Robot's avatar
Kitware Robot committed
461 462
  vtkPVPluginLoaderDebugMacro(
    "Plugin signature verification successful. "
463
    "This is definitely a ParaView plugin compiled with correct compiler for "
464 465
    "correct ParaView version."
    << endl);
466 467

  // BUG # 0008673
468
  // Tell the platform to look in the plugin's directory for
469 470 471
  // its dependencies. This isn't the right thing to do. A better
  // solution would be to let the plugin tell us where to look so
  // that a list of locations could be added.
472
  std::string ldLibPath;
473
#if defined(_WIN32) && !defined(__CYGWIN__)
Kitware Robot's avatar
Kitware Robot committed
474 475 476 477 478 479 480 481 482
  const char LIB_PATH_SEP = ';';
  const char PATH_SEP = '\\';
  const char* LIB_PATH_NAME = "PATH";
  ldLibPath = LIB_PATH_NAME;
  ldLibPath += '=';
#elif defined(__APPLE__)
  const char LIB_PATH_SEP = ':';
  const char PATH_SEP = '/';
  const char* LIB_PATH_NAME = "DYLD_LIBRARY_PATH";
483
#else
Kitware Robot's avatar
Kitware Robot committed
484 485 486
  const char LIB_PATH_SEP = ':';
  const char PATH_SEP = '/';
  const char* LIB_PATH_NAME = "LD_LIBRARY_PATH";
487
#endif
488
  // Trim the plugin name from the end of its path.
489
  std::string thisPluginsPath(file);
Kitware Robot's avatar
Kitware Robot committed
490 491
  size_t eop = thisPluginsPath.rfind(PATH_SEP);
  thisPluginsPath = thisPluginsPath.substr(0, eop);
492
  // Load the shared library search path.
Kitware Robot's avatar
Kitware Robot committed
493 494 495
  const char* pLdLibPath = getenv(LIB_PATH_NAME);
  bool pluginPathPresent =
    pLdLibPath == NULL ? false : strstr(pLdLibPath, thisPluginsPath.c_str()) != NULL;
496 497
  // Update it.
  if (!pluginPathPresent)
Kitware Robot's avatar
Kitware Robot committed
498
  {
499 500 501
    // Make sure we are only adding it once, because there can
    // be multiple plugins in the same folder.
    if (pLdLibPath)
Kitware Robot's avatar
Kitware Robot committed
502 503 504 505 506
    {
      ldLibPath += pLdLibPath;
      ldLibPath += LIB_PATH_SEP;
    }
    ldLibPath += thisPluginsPath;
507

508
    vtksys::SystemTools::PutEnv(ldLibPath);
509
    vtkPVPluginLoaderDebugMacro("Updating Shared Library Paths: " << ldLibPath << endl);
Kitware Robot's avatar
Kitware Robot committed
510
  }
511

512
  vtkPVPlugin* plugin = pv_plugin_query_instance();
Kitware Robot's avatar
Kitware Robot committed
513 514
  //  if (plugin->UnloadOnExit())
  {
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
515 516 517
    // So that the lib is closed when the application quits.
    // BUGS #10293, #15608.
    vtkPVPluginLoaderCleaner::GetInstance()->Register(plugin->GetPluginName(), lib);
Kitware Robot's avatar
Kitware Robot committed
518
  }
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
519

520
  return this->LoadPlugin(file, plugin);
521
#endif // ifndef BUILD_SHARED_LIBS else
522 523 524 525 526
}

//-----------------------------------------------------------------------------
bool vtkPVPluginLoader::LoadPlugin(const char* file, vtkPVPlugin* plugin)
{
527
#ifndef BUILD_SHARED_LIBS
Kitware Robot's avatar
Kitware Robot committed
528 529
  if (StaticPluginLoadFunction && StaticPluginLoadFunction(plugin->GetPluginName()))
  {
530 531
    this->Loaded = true;
    return true;
Kitware Robot's avatar
Kitware Robot committed
532
  }
533
  else
Kitware Robot's avatar
Kitware Robot committed
534
  {
535
    this->SetErrorString("Failed to load static plugin.");
Kitware Robot's avatar
Kitware Robot committed
536
  }
537 538
#endif

539 540 541 542
  this->SetPluginName(plugin->GetPluginName());
  this->SetPluginVersion(plugin->GetPluginVersionString());

  // Print some debug information about the plugin, if needed.
Kitware Robot's avatar
Kitware Robot committed
543 544
  vtkPVPluginLoaderDebugMacro(
    "Plugin instance located successfully. "
545
    "Now loading components from the plugin instance based on the interfaces it "
546 547
    "implements."
    << endl);
Kitware Robot's avatar
Kitware Robot committed
548 549 550 551 552 553 554 555 556 557 558
  vtkPVPluginLoaderDebugMacro("----------------------------------------------------------------\n"
                              "Plugin Information: \n"
                              "  Name        : "
    << plugin->GetPluginName() << "\n"
                                  "  Version     : "
    << plugin->GetPluginVersionString() << "\n"
                                           "  ReqOnServer : "
    << plugin->GetRequiredOnServer() << "\n"
                                        "  ReqOnClient : "
    << plugin->GetRequiredOnClient() << "\n"
                                        "  ReqPlugins  : "
559
    << plugin->GetRequiredPlugins() << endl);
560 561 562
  vtkPVServerManagerPluginInterface* smplugin =
    dynamic_cast<vtkPVServerManagerPluginInterface*>(plugin);
  if (smplugin)
Kitware Robot's avatar
Kitware Robot committed
563
  {
564
    vtkPVPluginLoaderDebugMacro("  ServerManager Plugin : Yes" << endl);
Kitware Robot's avatar
Kitware Robot committed
565
  }
566
  else
Kitware Robot's avatar
Kitware Robot committed
567
  {
568
    vtkPVPluginLoaderDebugMacro("  ServerManager Plugin : No" << endl);
Kitware Robot's avatar
Kitware Robot committed
569
  }
570

Kitware Robot's avatar
Kitware Robot committed
571
  vtkPVPythonPluginInterface* pyplugin = dynamic_cast<vtkPVPythonPluginInterface*>(plugin);
572
  if (pyplugin)
Kitware Robot's avatar
Kitware Robot committed
573
  {
574
    vtkPVPluginLoaderDebugMacro("  Python Plugin : Yes" << endl);
Kitware Robot's avatar
Kitware Robot committed
575
  }
576
  else
Kitware Robot's avatar
Kitware Robot committed
577
  {
578
    vtkPVPluginLoaderDebugMacro("  Python Plugin : No" << endl);
Kitware Robot's avatar
Kitware Robot committed
579
  }
580

Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
581 582 583 584
  // Set the filename so the vtkPVPluginTracker knows what file this plugin was
  // loaded from.
  plugin->SetFileName(file);

585 586 587 588
  // From this point onwards the vtkPVPlugin travels the same path as a
  // statically imported plugin.
  vtkPVPlugin::ImportPlugin(plugin);
  this->Loaded = true;
589

590
  return true;
591
}
592

593
//-----------------------------------------------------------------------------
Kitware Robot's avatar
Kitware Robot committed
594
void vtkPVPluginLoader::LoadPluginConfigurationXMLFromString(const char* xmlcontents)
595
{
Kitware Robot's avatar
Kitware Robot committed
596
  vtkPVPluginTracker::GetInstance()->LoadPluginConfigurationXMLFromString(xmlcontents);
597
}
598

599
//-----------------------------------------------------------------------------
600
void vtkPVPluginLoader::PrintSelf(ostream& os, vtkIndent indent)
601 602
{
  this->Superclass::PrintSelf(os, indent);
603
  os << indent << "DebugPlugin: " << this->DebugPlugin << endl;
Kitware Robot's avatar
Kitware Robot committed
604 605 606 607 608
  os << indent << "PluginName: " << (this->PluginName ? this->PluginName : "(none)") << endl;
  os << indent << "PluginVersion: " << (this->PluginVersion ? this->PluginVersion : "(none)")
     << endl;
  os << indent << "FileName: " << (this->FileName ? this->FileName : "(none)") << endl;
  os << indent << "SearchPaths: " << (this->SearchPaths ? this->SearchPaths : "(none)") << endl;
609
}
610 611 612 613 614

//-----------------------------------------------------------------------------
void vtkPVPluginLoader::SetStaticPluginLoadFunction(vtkPluginLoadFunction function)
{
  if (!StaticPluginLoadFunction)
Kitware Robot's avatar
Kitware Robot committed
615
  {
616
    StaticPluginLoadFunction = function;
Kitware Robot's avatar
Kitware Robot committed
617
  }
618
}
Utkarsh Ayachit's avatar
Utkarsh Ayachit committed
619 620 621 622 623 624

//-----------------------------------------------------------------------------
void vtkPVPluginLoader::PluginLibraryUnloaded(const char* pluginname)
{
  vtkPVPluginLoaderCleaner::PluginLibraryUnloaded(pluginname);
}