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 "../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 "../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?
73 
74  if(slib.get() != 0)
75  {
76 // if it already exists, just check if it is loaded
77  if(!slib->isLoaded())
78  slib->load();
79  }
80  else
81  {
82 // if not loaded yet, load it!
83 
84 // the plugin library file may be in a special dir informed by pInfo.m_folder
85 
86  std::string errorMessage;
87 
88  boost::filesystem::path pluginFile(libName);
89 
90  slib.reset(new te::common::Library(pluginFile.string(), true));
91 
92  try
93  {
94  slib->load();
95  }
96  catch(te::common::Exception& exc)
97  {
98  errorMessage = libName;
99  }
100 
101  if(!slib->isLoaded())
102  {
103 // search for alternative paths
104  std::vector<std::string> alternative_paths;
105 
106 #if TE_PLATFORM == TE_PLATFORMCODE_APPLE
107  alternative_paths.push_back("./");
108 #endif
109 
110 // 1st: in a place indicated by a environment variable defined in macro TERRALIB_DIR_VAR_NAME
111  const char* home_dir = getenv(TERRALIB_DIR_VAR_NAME);
112 
113  if(home_dir != 0)
114  alternative_paths.push_back(home_dir);
115 
116 // 2nd: in the install prefix dir
117  alternative_paths.push_back(TERRALIB_INSTALL_PREFIX_PATH);
118 
119  for(std::size_t i = 0; i != alternative_paths.size(); ++i)
120  {
121  try
122  {
123  pluginFile = alternative_paths[i];
124  pluginFile /= libName;
125  slib.reset(new te::common::Library(pluginFile.string(), true));
126  slib->load();
127  errorMessage.clear();
128  break;
129  }
130  catch(te::common::Exception& exc)
131  {
132  errorMessage += '\n';
133  errorMessage += pluginFile.string();
134  }
135 
136  try
137  {
138  pluginFile = alternative_paths[i];
139  pluginFile /= "lib";
140  pluginFile /= libName;
141  slib.reset(new te::common::Library(pluginFile.string(), true));
142  slib->load();
143  errorMessage.clear();
144  break;
145  }
146  catch(te::common::Exception& exc)
147  {
148  errorMessage += '\n';
149  errorMessage += pluginFile.string();
150  }
151 
152 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
153  try
154  {
155  pluginFile = alternative_paths[i];
156  pluginFile /= "Release";
157  pluginFile /= libName;
158  slib.reset(new te::common::Library(pluginFile.string(), true));
159  slib->load();
160  errorMessage.clear();
161  break;
162  }
163  catch(te::common::Exception& exc)
164  {
165  errorMessage += '\n';
166  errorMessage += pluginFile.string();
167  }
168 
169  try
170  {
171  pluginFile = alternative_paths[i];
172  pluginFile /= "Debug";
173  pluginFile /= libName;
174  slib.reset(new te::common::Library(pluginFile.string(), true));
175  slib->load();
176  errorMessage.clear();
177  break;
178  }
179  catch(te::common::Exception& exc)
180  {
181  errorMessage += '\n';
182  errorMessage += pluginFile.string();
183  }
184 #endif
185  }
186 
187  if(!slib->isLoaded())
188  {
189  std::string m = TE_TR("Could not find shared library as: ");
190  if (!errorMessage.empty())
191  m = m + "\n" + errorMessage.c_str();
192  else
193  m = m + ' '+ TE_TR("descried in ") + pInfo.m_name + '.';
194 
195  throw te::common::Exception(m);
196  }
197  }
198  }
199 
200  if(slib.get() == 0)
201  {
202  std::string m = TE_TR("Could not find shared library described in ");
203  m += pInfo.m_name;
204  throw te::common::Exception(m);
205  }
206 
207 // now we need to get the plugin constructor function address
208  GetPluginFPtr getPluginFptr = (GetPluginFPtr) (slib->getAddress("CppPluginGetInstance"));
209 
210  if(getPluginFptr == NULL)
211  {
212  std::string m = TE_TR("Could not find CppPluginGetInstance function into the plugin's code: ");
213  m += pInfo.m_name;
214  m += "!";
215 
216  throw te::common::Exception(m);
217  }
218 
219  std::auto_ptr<Plugin> cppPlugin(getPluginFptr(pInfo));
220 
221  if(cppPlugin.get() == 0)
222  {
223  std::string m = TE_TR("CppPluginGetInstance returned a null plugin instance: ");
224  m += pInfo.m_name;
225  m += "!";
226 
227  throw te::common::Exception(m);
228  }
229 
230  CppPluginProxy* proxy = new CppPluginProxy(slib, cppPlugin.release());
231 
233 
234  return proxy;
235 }
236 
238 {
239  assert(plugin && (plugin->getInfo().m_engine == "C++"));
240 
241  delete plugin;
242 }
243 
244 std::string te::plugin::CppPluginEngine::getPluginFileName(const std::string& libName)
245 {
246  std::string nativeName = te::common::Library::getNativeName(libName);
247 
248  return nativeName;
249 }
250 
A base class for plugin types.
A plugin engine for plugins written in C++.
boost::shared_ptr< Library > LibraryPtr
Definition: Library.h:184
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
virtual const PluginInfo & getInfo() const =0
It return the information associated to the plugin.
Plugin *(* GetPluginFPtr)(const PluginInfo &info)
It exports Plugin's access function type.
Definition: Plugin.h:92
An abstract class for TerraLib Plugins.
A class for handling shared libraries (DLLs, SO, DyLibs).
Definition: Library.h:58
void unload(AbstractPlugin *plugin)
It try to unload the informed 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:346
A proxy class for C++ plugins.
std::string m_engine
The type of plugin execution engine: C++, JAVA.
Definition: PluginInfo.h:71
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:189
static LibraryManager & getInstance()
It returns a reference to the singleton instance.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
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.
Definition: PluginInfo.h:81
A proxy class for C++ plugins.
The basic information about a plugin.
Definition: PluginInfo.h:61
void add(const std::string &id, const LibraryPtr &l)
It adds a new Library to be managed.
The basic information about a plugin.