attic/src/plugin/CppPluginEngine.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/plugin/CppPluginEngine.cpp
22 
23  \brief A plugin engine for plugins written in C++.
24 */
25 
26 // TerraLib
27 #include "../common/Exception.h"
28 #include "../core/lib/Library.h"
29 #include "../core/lib/LibraryManager.h"
30 #include "../core/logger/Logger.h"
31 #include "../core/translator/Translator.h"
32 #include "../common/PlatformUtils.h"
33 #include "../Defines.h"
34 #include "CppPluginEngine.h"
35 #include "CppPluginProxy.h"
36 #include "Plugin.h"
37 #include "PluginInfo.h"
38 
39 // STL
40 #include <algorithm>
41 #include <cassert>
42 #include <functional>
43 #include <memory>
44 
45 // Boost
46 #include <boost/filesystem.hpp>
47 
49 {
50 }
51 
53 {
54 // get the plugin's shared library name in the resources list
55  std::vector<PluginInfo::Resource>::const_iterator it = std::find_if(pInfo.m_resources.begin(),
56  pInfo.m_resources.end(),
57  PluginInfo::Finder1st("SharedLibraryName"));
58 
59  if(it == pInfo.m_resources.end())
60  {
61  std::string m = TE_TR("Shared library name not informed for plugin: ");
62  m += pInfo.m_name;
63  m += "!";
64 
65  throw te::common::Exception(m);
66  }
67 
68 // get the adequate name depending on the platform and build type (release or debug)
69  std::string libName = getPluginFileName(it->second);
70 
71 // is there a library already loaded with this name?
72  std::shared_ptr<te::core::Library> slib(new te::core::Library(libName));
73 
74  if(!slib->isLoaded())
75  slib->load();
76  else
77  {
78 // if not loaded yet, load it!
79 
80 // the plugin library file may be in a special dir informed by pInfo.m_folder
81 
82  std::string errorMessage;
83 
84  boost::filesystem::path pluginFile(libName);
85 
86  slib.reset(new te::core::Library(pluginFile.string(), true));
87 
88  try
89  {
90  slib->load();
91  }
92  catch(te::common::Exception& exc)
93  {
94  errorMessage = libName;
95  }
96 
97  if(!slib->isLoaded())
98  {
99 // search for alternative paths
100  std::vector<std::string> alternative_paths;
101 
102 #if TE_PLATFORM == TE_PLATFORMCODE_APPLE
103  alternative_paths.push_back("./");
104 #endif
105 
106 // 1st: in a place indicated by a environment variable defined in macro TERRALIB_DIR_VAR_NAME
107  const char* home_dir = getenv(TERRALIB_DIR_VAR_NAME);
108 
109  if(home_dir != 0)
110  alternative_paths.push_back(home_dir);
111 
112 // 2nd: in the install prefix dir
113  alternative_paths.push_back(TERRALIB_INSTALL_PREFIX_PATH);
114 
115  for(std::size_t i = 0; i != alternative_paths.size(); ++i)
116  {
117  try
118  {
119  pluginFile = alternative_paths[i];
120  pluginFile /= libName;
121  slib.reset(new te::core::Library(pluginFile.string(), true));
122  slib->load();
123  errorMessage.clear();
124  break;
125  }
126  catch(te::common::Exception& exc)
127  {
128  errorMessage += '\n';
129  errorMessage += pluginFile.string();
130  }
131 
132  try
133  {
134  pluginFile = alternative_paths[i];
135  pluginFile /= "lib";
136  pluginFile /= libName;
137  slib.reset(new te::core::Library(pluginFile.string(), true));
138  slib->load();
139  errorMessage.clear();
140  break;
141  }
142  catch(te::common::Exception& exc)
143  {
144  errorMessage += '\n';
145  errorMessage += pluginFile.string();
146  }
147 
148 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
149  try
150  {
151  pluginFile = alternative_paths[i];
152  pluginFile /= "Release";
153  pluginFile /= libName;
154  slib.reset(new te::core::Library(pluginFile.string(), true));
155  slib->load();
156  errorMessage.clear();
157  break;
158  }
159  catch(te::common::Exception& exc)
160  {
161  errorMessage += '\n';
162  errorMessage += pluginFile.string();
163  }
164 
165  try
166  {
167  pluginFile = alternative_paths[i];
168  pluginFile /= "Debug";
169  pluginFile /= libName;
170  slib.reset(new te::core::Library(pluginFile.string(), true));
171  slib->load();
172  errorMessage.clear();
173  break;
174  }
175  catch(te::common::Exception& exc)
176  {
177  errorMessage += '\n';
178  errorMessage += pluginFile.string();
179  }
180 #endif
181  }
182 
183  if(!slib->isLoaded())
184  {
185  std::string m = TE_TR("Could not find shared library as: ");
186  if (!errorMessage.empty())
187  m = m + "\n" + errorMessage.c_str();
188  else
189  m = m + ' '+ TE_TR("described in ") + pInfo.m_name + '.';
190 
191  throw te::common::Exception(m);
192  }
193  }
194  }
195 
196  if(slib.get() == 0)
197  {
198  std::string m = TE_TR("Could not find shared library described in ");
199  m += pInfo.m_name;
200  throw te::common::Exception(m);
201  }
202 
203 // now we need to get the plugin constructor function address
204  GetPluginFPtr getPluginFptr = (GetPluginFPtr) (slib->getAddress("CppPluginGetInstance"));
205 
206  if(getPluginFptr == NULL)
207  {
208  std::string m = TE_TR("Could not find CppPluginGetInstance function into the plugin's code: ");
209  m += pInfo.m_name;
210  m += "!";
211 
212  throw te::common::Exception(m);
213  }
214 
215  std::auto_ptr<Plugin> cppPlugin(getPluginFptr(pInfo));
216 
217  if(cppPlugin.get() == 0)
218  {
219  std::string m = TE_TR("CppPluginGetInstance returned a null plugin instance: ");
220  m += pInfo.m_name;
221  m += "!";
222 
223  throw te::common::Exception(m);
224  }
225 
226  CppPluginProxy* proxy = new CppPluginProxy(slib, cppPlugin.release());
227 
228 
229  return proxy;
230 }
231 
233 {
234  assert(plugin && (plugin->getInfo().m_engine == "C++"));
235 
236  delete plugin;
237 }
238 
239 std::string te::plugin::CppPluginEngine::getPluginFileName(const std::string& libName)
240 {
241  std::string nativeName = te::core::Library::getNativeName(libName);
242 
243  return nativeName;
244 }
245 
std::string m_name
The plugin name: an internal value used to identify the plugin in the system. Must be a unique value...
Plugin *(* GetPluginFPtr)(const PluginInfo &info)
It exports Plugin&#39;s access function type.
An abstract class for TerraLib Plugins.
void unload(AbstractPlugin *plugin)
It try to unload the informed plugin.
virtual const PluginInfo & getInfo() const =0
It return the information associated to the plugin.
static std::string getPluginFileName(const std::string &libName)
This method will help to form the library name wich contains the plugin.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
A class for handling shared libraries (DLLs, SO, DyLibs).
Definition: Library.h:73
A proxy class for C++ plugins.
std::string m_engine
The type of plugin execution engine: C++, JAVA.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
AbstractPlugin * load(const PluginInfo &pInfo)
It try to create and load the informed plugin.
std::vector< Resource > m_resources
The list of resources used by plugin.
The basic information about a plugin.
static std::string getNativeName(const std::string &name)
Given a shared library name without file extensions, prefixes and nor suffixes it will construct a li...
Definition: Library.cpp:256