All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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  boost::filesystem::path pluginFile(libName);
86 
87  slib.reset(new te::common::Library(pluginFile.string(), true));
88 
89  try
90  {
91  slib->load();
92  }
93  catch(...)
94  {
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::common::Library(pluginFile.string(), true));
122  slib->load();
123  break;
124  }
125  catch(...)
126  {
127  }
128 
129  try
130  {
131  pluginFile = alternative_paths[i];
132  pluginFile /= "lib";
133  pluginFile /= libName;
134  slib.reset(new te::common::Library(pluginFile.string(), true));
135  slib->load();
136  break;
137  }
138  catch(...)
139  {
140  }
141 
142 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
143  try
144  {
145  pluginFile = alternative_paths[i];
146  pluginFile /= "Release";
147  pluginFile /= libName;
148  slib.reset(new te::common::Library(pluginFile.string(), true));
149  slib->load();
150  break;
151  }
152  catch(...)
153  {
154  }
155 
156  try
157  {
158  pluginFile = alternative_paths[i];
159  pluginFile /= "Debug";
160  pluginFile /= libName;
161  slib.reset(new te::common::Library(pluginFile.string(), true));
162  slib->load();
163  break;
164  }
165  catch(...)
166  {
167  }
168 #endif
169  }
170 
171  if(!slib->isLoaded())
172  {
173  std::string m = TE_TR("Could not find shared library: ");
174  m += pInfo.m_name;
175  throw te::common::Exception(m);
176  }
177  }
178  }
179 
180  if(slib.get() == 0)
181  {
182  std::string m = TE_TR("Could not find shared library: ");
183  m += pInfo.m_name;
184  throw te::common::Exception(m);
185  }
186 
187 // now we need to get the plugin constructor function address
188  GetPluginFPtr getPluginFptr = (GetPluginFPtr) (slib->getAddress("CppPluginGetInstance"));
189 
190  if(getPluginFptr == NULL)
191  {
192  std::string m = TE_TR("Could not find CppPluginGetInstance function into the plugin's code: ");
193  m += pInfo.m_name;
194  m += "!";
195 
196  throw te::common::Exception(m);
197  }
198 
199  std::auto_ptr<Plugin> cppPlugin(getPluginFptr(pInfo));
200 
201  if(cppPlugin.get() == 0)
202  {
203  std::string m = TE_TR("CppPluginGetInstance returned a null plugin instance: ");
204  m += pInfo.m_name;
205  m += "!";
206 
207  throw te::common::Exception(m);
208  }
209 
210  CppPluginProxy* proxy = new CppPluginProxy(slib, cppPlugin.release());
211 
213 
214  return proxy;
215 }
216 
218 {
219  assert(plugin && (plugin->getInfo().m_engine == "C++"));
220 
221  delete plugin;
222 }
223 
224 std::string te::plugin::CppPluginEngine::getPluginFileName(const std::string& libName)
225 {
226  std::string nativeName = te::common::Library::getNativeName(libName);
227 
228  return nativeName;
229 }
230 
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:347
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.