All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CppPluginEngine.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2001-2009 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 "../common/Library.h"
29 #include "../common/LibraryManager.h"
30 #include "../common/Logger.h"
31 #include "../common/Translator.h"
32 #include "../common/PlatformUtils.h"
33 #include "CppPluginEngine.h"
34 #include "CppPluginProxy.h"
35 #include "Plugin.h"
36 #include "PluginInfo.h"
37 
38 // STL
39 #include <algorithm>
40 #include <cassert>
41 #include <functional>
42 #include <memory>
43 
44 // Boost
45 #include <boost/filesystem.hpp>
46 
48 {
50 }
51 
53 {
54  PluginInfo internalPluginInfo = pInfo;
55 
56 // get the plugin's shared library name in the resources list
57  std::vector<PluginInfo::Resource>::const_iterator it = std::find_if(internalPluginInfo.m_resources.begin(),
58  internalPluginInfo.m_resources.end(),
59  PluginInfo::Finder1st("SharedLibraryName"));
60 
61  if(it == internalPluginInfo.m_resources.end())
62  {
63  std::string m = TR_PLUGIN("Shared library name not informed for plugin: ");
64  m += pInfo.m_name;
65  m += "!";
66 
67  throw te::common::Exception(m);
68  }
69 
70 // get the adequate name depending on the platform and build type (release or debug)
71  std::string libName = getPluginFileName(it->second);
72 
73 // is there a library already loaded with this name?
75 
76  if(slib.get() == 0)
77  {
78 // if not loaded, load it!
79 
80  boost::filesystem::path pluginFile( internalPluginInfo.m_folder );
81  pluginFile /= libName;
82 
83 // the plugin library file may be in a special dir informed by internalPluginInfo.m_folder
84  if( boost::filesystem::exists(pluginFile) &&
85  boost::filesystem::is_regular_file(pluginFile) )
86  {
87  // create shared library entry but doesn't load it yet!
88  slib.reset(new te::common::Library(pluginFile.string(), true));
89  }
90  else
91  {
92  for( std::vector< std::string >::size_type dirIdx = 0 ; dirIdx <
93  m_defaultSearchDirs.size() ; ++dirIdx )
94  {
95  pluginFile = m_defaultSearchDirs[ dirIdx ];
96  pluginFile /= libName;
97 
98  if(boost::filesystem::exists(pluginFile) &&
99  boost::filesystem::is_regular_file(pluginFile) )
100  {
101  internalPluginInfo.m_folder = m_defaultSearchDirs[ dirIdx ];
102  slib.reset(new te::common::Library(pluginFile.string(), true));
103  break;
104  }
105  }
106  }
107  }
108 
109  if(slib.get() == 0)
110  {
111  std::string m = TR_PLUGIN("Could not find load plugin: ");
112  m += internalPluginInfo.m_name;
113  throw te::common::Exception(m);
114  }
115 
116  if(!slib->isLoaded())
117  slib->load();
118 
119 // now we need to get the plugin constructor function address
120  GetPluginFPtr getPluginFptr = (GetPluginFPtr) (slib->getAddress("CppPluginGetInstance"));
121 
122  if(getPluginFptr == NULL)
123  {
124  std::string m = TR_PLUGIN("Could not find CppPluginGetInstance function into the plugin's code: ");
125  m += internalPluginInfo.m_name;
126  m += "!";
127 
128  throw te::common::Exception(m);
129  }
130 
131  std::auto_ptr<Plugin> cppPlugin(getPluginFptr(internalPluginInfo));
132 
133  if(cppPlugin.get() == 0)
134  {
135  std::string m = TR_PLUGIN("CppPluginGetInstance returned a null plugin instance: ");
136  m += internalPluginInfo.m_name;
137  m += "!";
138 
139  throw te::common::Exception(m);
140  }
141 
142  CppPluginProxy* proxy = new CppPluginProxy(slib, cppPlugin.release());
143 
145 
146  return proxy;
147 }
148 
150 {
151  assert(plugin && (plugin->getInfo().m_engine == "C++"));
152 
153  delete plugin;
154 }
155 
156 std::string te::plugin::CppPluginEngine::getPluginFileName(const std::string& libName)
157 {
158 #ifdef NDEBUG
159  std::string nativeName = libName;
160 #else
161  std::string nativeName = libName + "_d"; // add a suffix _d to the library name in debug mode
162 #endif
163  nativeName = te::common::Library::getNativeName(nativeName);
164 
165  return nativeName;
166 }
167 
168 void te::plugin::CppPluginEngine::getDefaultDirs( std::vector< std::string >& dirs )
169 {
170  dirs.clear();
171 
172  dirs.push_back( "." );
173 
174  {
175  boost::filesystem::path p("lib");
176 
177  if(boost::filesystem::is_directory(p))
178  dirs.push_back( boost::filesystem::system_complete( p ).string() );
179  }
180 
181  {
182  boost::filesystem::path p("win32");
183 
184  if(boost::filesystem::is_directory(p))
185  dirs.push_back( boost::filesystem::system_complete( p ).string() );
186  }
187 
188  {
189  boost::filesystem::path p("win64");
190 
191  if(boost::filesystem::is_directory(p))
192  dirs.push_back( boost::filesystem::system_complete( p ).string() );
193  }
194 
195  #ifdef TE_DEFAULT_PLUGINS_DIR
196  if(boost::filesystem::is_directory(TE_DEFAULT_PLUGINS_DIR))
197  {
198  dirs.push_back( boost::filesystem::system_complete(TE_DEFAULT_PLUGINS_DIR).string() );
199  }
200  #endif
201 
202  #ifdef TE_DIR_ENVIRONMENT_VARIABLE
203  {
204  char* e = getenv(TE_DIR_ENVIRONMENT_VARIABLE);
205 
206  if(e != 0)
207  {
208  if(boost::filesystem::is_directory(e))
209  dirs.push_back( boost::filesystem::system_complete(e).string() );
210 
211  {
212  boost::filesystem::path p(e);
213  p /= "lib";
214 
215  if(boost::filesystem::is_directory(p))
216  dirs.push_back( boost::filesystem::system_complete(p).string() );
217  }
218 
219  {
220  boost::filesystem::path p(e);
221  p /= "bin32";
222 
223  if(boost::filesystem::is_directory(p))
224  dirs.push_back( boost::filesystem::system_complete(p).string() );
225  }
226 
227  {
228  boost::filesystem::path p(e);
229  p /= "bin64";
230 
231  if(boost::filesystem::is_directory(p))
232  dirs.push_back( boost::filesystem::system_complete(p).string() );
233  }
234 
235  #ifdef TE_DEFAULT_PLUGINS_DIR
236  {
237  boost::filesystem::path p(e);
239 
240  if(boost::filesystem::is_directory(p))
241  dirs.push_back( boost::filesystem::system_complete(p).string() );
242  }
243  #endif
244  }
245  }
246  #endif
247 
248  {
249  char* e = getenv("TERRALIB_DIR");
250 
251  if(e != 0)
252  {
253  if(boost::filesystem::is_directory(e))
254  dirs.push_back( boost::filesystem::system_complete(e).string() );
255 
256  {
257  boost::filesystem::path p(e);
258  p /= "lib";
259 
260  if(boost::filesystem::is_directory(p))
261  dirs.push_back( boost::filesystem::system_complete(p).string() );
262  }
263 
264  {
265  boost::filesystem::path p(e);
266  p /= "bin32";
267 
268  if(boost::filesystem::is_directory(p))
269  dirs.push_back( boost::filesystem::system_complete(p).string() );
270  }
271 
272  {
273  boost::filesystem::path p(e);
274  p /= "bin64";
275 
276  if(boost::filesystem::is_directory(p))
277  dirs.push_back( boost::filesystem::system_complete(p).string() );
278  }
279 
280  #ifdef TE_DEFAULT_PLUGINS_DIR
281  {
282  boost::filesystem::path p(e);
284 
285  if(boost::filesystem::is_directory(p))
286  dirs.push_back( boost::filesystem::system_complete(p).string() );
287  }
288  #endif
289  }
290  }
291 
292  #ifdef TE_PLUGINS_PATH
293  {
294  if(boost::filesystem::is_directory(TE_PLUGINS_PATH))
295  dirs.push_back( boost::filesystem::system_complete(TE_PLUGINS_PATH).string() );
296 
297  {
298  boost::filesystem::path p(TE_PLUGINS_PATH);
299  p /= "lib";
300 
301  if(boost::filesystem::is_directory(p))
302  dirs.push_back( boost::filesystem::system_complete(p).string() );
303  }
304 
305  {
306  boost::filesystem::path p(TE_PLUGINS_PATH);
307  p /= "bin32";
308 
309  if(boost::filesystem::is_directory(p))
310  dirs.push_back( boost::filesystem::system_complete(p).string() );
311  }
312 
313  {
314  boost::filesystem::path p(TE_PLUGINS_PATH);
315  p /= "bin64";
316 
317  if(boost::filesystem::is_directory(p))
318  dirs.push_back( boost::filesystem::system_complete(p).string() );
319  }
320 
321  #ifdef TE_DEFAULT_PLUGINS_DIR
322  {
323  boost::filesystem::path p(TE_PLUGINS_PATH);
325 
326  if(boost::filesystem::is_directory(p))
327  dirs.push_back( boost::filesystem::system_complete(p).string() );
328  }
329  #endif
330  }
331  #endif
332 
333  std::vector< std::string > decPath;
335  for( std::vector< std::string >::size_type decPathIdx = 0 ; decPathIdx < decPath.size() ;
336  ++decPathIdx )
337  {
338  dirs.push_back( decPath[ decPathIdx ] );
339  }
340 
341  std::vector< std::string > decLDPath;
343  for( std::vector< std::string >::size_type decLDPathIdx = 0 ; decLDPathIdx < decLDPath.size() ;
344  ++decLDPathIdx )
345  {
346  dirs.push_back( decLDPath[ decLDPathIdx ] );
347  }
348 }
349 
void GetDecompostedPathEnvVar(std::vector< std::string > &paths)
Returns the system PATH enviroment variable, decomposed into directory names, or an empty vector if n...
The basic information about a plugin.
Definition: PluginInfo.h:61
A proxy class for C++ plugins.
The basic information about a plugin.
std::vector< std::string > m_defaultSearchDirs
The default plugin libraries search directories.
void unload(AbstractPlugin *plugin)
It try to unload the informed plugin.
An abstract class for TerraLib Plugins.
static std::string getPluginFileName(const std::string &libName)
This method will help to form the library name wich contains the plugin.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
std::vector< Resource > m_resources
The list of resources used by plugin.
Definition: PluginInfo.h:82
#define TR_PLUGIN(message)
It marks a string in order to get translated. This is a special mark used in the Plugin module of Ter...
Definition: Config.h:117
static std::string getNativeName(const std::string &name)
Given a library name without file extensions, prefixes and nor suffixes it will construct a library n...
Definition: Library.cpp:188
Plugin *(* GetPluginFPtr)(const PluginInfo &info)
It exports Plugin&#39;s access function type.
Definition: Plugin.h:92
void add(const std::string &id, const LibraryPtr &l)
It adds a new Library to be managed.
A plugin engine for plugins written in C++.
A class for handling shared libraries (DLLs, SO, DyLibs).
Definition: Library.h:58
void GetDecompostedLDPathEnvVar(std::vector< std::string > &paths)
Returns the system LD_LIBRARY_PATH enviroment variable, decomposed into directory names...
#define TE_DEFAULT_PLUGINS_DIR
The default look up plugin dir.
Definition: Config.h:75
A proxy class for C++ plugins.
AbstractPlugin * load(const PluginInfo &pInfo)
It try to create and load the informed plugin.
virtual const PluginInfo & getInfo() const =0
It return the information associated to the plugin.
boost::shared_ptr< Library > LibraryPtr
Definition: Library.h:184
std::string m_engine
The type of plugin execution engine: C++, JAVA.
Definition: PluginInfo.h:71
static LibraryManager & getInstance()
It returns a reference to the singleton instance.
std::string m_name
The plugin name: an internal value used to identify the plugin in the system. Must be a unique value...
Definition: PluginInfo.h:66
static void getDefaultDirs(std::vector< std::string > &dirs)
It returns the default plugins libraries search directories.
A base class for plugin types.
std::string m_folder
The plugin folder (where the plugin is installed).
Definition: PluginInfo.h:78