All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Library.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/common/Library.cpp
22 
23  \brief A class for handling shared libraries.
24 */
25 
26 // TerraLib
27 #include "../Defines.h"
28 #include "Exception.h"
29 #include "Library.h"
30 #include "PlatformUtils.h"
31 #include "Translator.h"
32 
33 // Boost
34 #include <boost/format.hpp>
35 
36 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
37 #include <windows.h>
38 
39 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
40 #include <cstdlib>
41 #include <dlfcn.h>
42 #else
43  #error "Platform not supported! Please, contact the TerraLib team (terralib-team@dpi.inpe.br) for helping support this platform!"
44 #endif
45 
46 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
47 static bool sg_addedSearchPath(false); //!< This flag is very important for Windows because some routines in its API returns 0 with two meanings: error or empty, but there is no way to know which one is right!
48 #endif
49 
51 {
52  public:
53 
54  Impl(const std::string& fileName, bool delayLoad) throw(te::common::Exception)
55  : m_fileName(fileName),
56  m_module(0)
57  {
58  if(delayLoad)
59  return;
60 
61  load();
62  }
63 
65  {
66  unload();
67  }
68 
69  void load() throw(te::common::Exception)
70  {
71  if(m_module)
72  return;
73 
74 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
75  m_module = (void*)LoadLibraryA(m_fileName.c_str());
76 
77 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
78  m_module = dlopen(m_fileName.c_str(), RTLD_NOW);
79 
80 #else
81  #error "Platform not supported! Please, contact the TerraLib team (terralib-team@dpi.inpe.br) for helping support this platform!"
82 #endif
83 
84  if(m_module == 0)
85 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
86  throw te::common::Exception((boost::format(TE_TR("Could not load library: %1%, due to following error: %2%.")) % m_fileName % te::common::win::GetLastError()).str());
87 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
88  throw te::common::Exception((boost::format(TE_TR("Could not load library: %1%, due to following error: %2%.")) % m_fileName % te::common::lx::GetDlError()).str());
89 #else
90  #error "Platform not supported! Please, contact the TerraLib team (terralib-team@dpi.inpe.br) for helping support this platform!"
91 #endif
92  }
93 
94  void unload() throw(te::common::Exception)
95  {
96  if(m_module == 0)
97  return;
98 
99 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
100  BOOL result = FreeLibrary((HMODULE)m_module);
101 
102  if(result == FALSE)
103  throw te::common::Exception((boost::format(TE_TR("Could not unload library: %1%, due to following error: %2%.")) % m_fileName % te::common::win::GetLastError()).str());
104 
105 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
106  if(dlclose(m_module))
107  throw Exception((boost::format(TE_TR("Could not unload library: %1%, due to following error: %2%.")) % m_fileName % te::common::lx::GetDlError()).str());
108 #else
109  #error "Platform not supported! Please, contact the TerraLib team (terralib-team@dpi.inpe.br) for helping support this platform!"
110 #endif
111 
112  m_module = 0;
113  }
114 
115  bool isLoaded() const throw()
116  {
117  return (m_module != 0);
118  }
119 
120  const std::string& getFileName() const throw()
121  {
122  return m_fileName;
123  }
124 
125  void* getAddress(const std::string& symbol) const throw(te::common::Exception)
126  {
127 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
128  void* f = GetProcAddress((HMODULE)m_module, symbol.c_str());
129 #elif TE_PLATFORM == TE_PLATFORMCODE_LINUX || TE_PLATFORM == TE_PLATFORMCODE_APPLE
130  void* f = dlsym(m_module, symbol.c_str());
131 #else
132  #error "Platform not supported! Please, contact the TerraLib team for helping support this platform!"
133 #endif
134 
135  if(f == NULL)
136 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
137  throw Exception((boost::format(TE_TR("Could not find symbol: %1%, in the library %2%, due to the following error: %3%.")) % symbol % m_fileName % te::common::win::GetLastError()).str());
138 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
139  throw Exception((boost::format(TE_TR("Could not find symbol: %1%, in the library %2%, due to the following error: %3%.")) % symbol % m_fileName % te::common::lx::GetDlError()).str());
140 #else
141  #error "Platform not supported! Please, contact terralib-team@dpi.inpe.br for helping support this platform!"
142 #endif
143 
144  return f;
145  }
146 
147  private:
148 
149  std::string m_fileName; //!< The library file name with full path.
150  void* m_module; //!< The handle for DLLs, SO or a DyLib.
151 };
152 
153 te::common::Library::Library(const std::string& fileName, bool delayLoad) throw(Exception)
154  : m_pImpl(0)
155 {
156  m_pImpl = new Impl(fileName, delayLoad);
157 }
158 
160 {
161  delete m_pImpl;
162 }
163 
165 {
166  m_pImpl->load();
167 }
168 
170 {
171  m_pImpl->unload();
172 }
173 
174 bool te::common::Library::isLoaded() const throw()
175 {
176  return m_pImpl->isLoaded();
177 }
178 
179 const std::string& te::common::Library::getFileName() const throw()
180 {
181  return m_pImpl->getFileName();
182 }
183 
184 void* te::common::Library::getAddress(const std::string& symbol) const throw(Exception)
185 {
186  return m_pImpl->getAddress(symbol);
187 }
188 
189 std::string te::common::Library::getNativeName(const std::string& name) throw()
190 {
191 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
192  std::string nativeName = name + ".dll";
193 
194 #elif TE_PLATFORM == TE_PLATFORMCODE_LINUX
195  std::string nativeName = "lib" + name + ".so";
196 
197 #elif TE_PLATFORM == TE_PLATFORMCODE_APPLE
198  std::string nativeName = "lib" + name + ".dylib";
199 
200 #else
201  #error "Platform not supported! Please, contact the TerraLib team (terralib-team@dpi.inpe.br) for helping support this platform!"
202 #endif
203 
204  return nativeName;
205 }
206 
207 void te::common::Library::addSearchDir(const std::string& d) throw(Exception)
208 {
209 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
210  if(d.length() > (MAX_PATH - 2))
211  throw Exception((boost::format(TE_TR("The DLL lookup path is too long: %1%.")) % d).str());
212 
213 // add dir to the path of LoadLibrary
214  BOOL retval = SetDllDirectory(d.c_str());
215 
216  if(retval == FALSE)
217  throw Exception((boost::format(TE_TR("The informed dir \"%1%\" couldn't be added to the application dll lookup path due to the following error: %2%.")) % d % te::common::win::GetLastError()).str());
218 
219  sg_addedSearchPath = true;
220 
221 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
222 
223  const char* ldLibraryPath = getenv("LD_LIBRARY_PATH");
224 
225  if(ldLibraryPath == 0)
226  {
227 // LD_LIBRARY_PATH doesn't exist
228  int result = setenv("LD_LIBRARY_PATH", d.c_str(), 1);
229 
230  if(result)
231  throw Exception((boost::format(TE_TR("Could not create LD_LIBRARY_PATH for the application. It is not pointing to the informed dir \"%1%\".")) % d).str());
232  }
233  else
234  {
235 // LD_LIBRARY_PATH may be empty or may have any other value, we need to concatenate
236  std::string newLdLibraryPath(ldLibraryPath);
237  newLdLibraryPath += ";";
238  newLdLibraryPath += d;
239 
240  int result = setenv("LD_LIBRARY_PATH", newLdLibraryPath.c_str(), 1);
241 
242  if(result)
243  throw Exception((boost::format(TE_TR("Couldn't add the informed dir \"%1%\" to the application's environment variable LD_LIBRARY_PATH.")) % d).str());
244  }
245 
246 #else
247  throw Exception(TE_TR("method: void te::common::Library::addSearchDir(const std::string& d) throw(Exception) not implemented for this platform! Contact terralib-team@dpi.inpe.br"));
248 #endif
249 }
250 
252 {
253 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
254 // come back with default Windows path
255  BOOL retval = SetDllDirectory("");
256 
257  if(retval == FALSE)
258  throw Exception((boost::format(TE_TR("Couldn't come back with default Windows DLL lookup path due to the following error: %1%.")) % te::common::win::GetLastError()).str());
259 
260  sg_addedSearchPath = false;
261 
262 #else
263  throw Exception(TE_TR("method: void te::common::Library::resetSearchPath() throw(Exception) not implemented for this platform! Contact terralib-team@dpi.inpe.br"));
264 #endif
265 }
266 
268 {
269 #if TE_PLATFORM == TE_PLATFORMCODE_MSWINDOWS
270  const DWORD buffSize = 32768;
271 
272  char buff[buffSize];
273 
274  DWORD length = GetDllDirectory(buffSize, buff);
275 
276  if(length == 0 && sg_addedSearchPath)
277  throw Exception((boost::format(TE_TR("Couldn't get Windows DLL lookup path due to the following error: %1%!")) % te::common::win::GetLastError()).str());
278 
279  if(length <= buffSize)
280  return std::string(buff, length);
281 
282  throw Exception(TE_TR("Windows DLL lookup path too long!"));
283 
284 #elif (TE_PLATFORM == TE_PLATFORMCODE_LINUX) || (TE_PLATFORM == TE_PLATFORMCODE_APPLE)
285 
286  const char* ldLibraryPath = getenv("LD_LIBRARY_PATH");
287 
288  if(ldLibraryPath == 0)
289  return std::string("");
290  else
291  return std::string(ldLibraryPath);
292 
293 #else
294  #warning "Verify the method: std::string te::common::Library::getSearchPath() throw(std::exception) for this platform!"
295 #endif
296 }
297 
static bool sg_addedSearchPath(false)
This flag is very important for Windows because some routines in its API returns 0 with two meanings:...
Impl(const std::string &fileName, bool delayLoad)
Definition: Library.cpp:54
static void resetSearchPath()
It comes back the application lookupo path to the original state, before any addPath has been called...
Definition: Library.cpp:251
This file is a wrapper around platform specific include files.
A class for handling shared libraries.
bool isLoaded() const
It returns true if the shared library is loaded otherwise return false.
Definition: Library.cpp:174
void * getAddress(const std::string &symbol) const
Definition: Library.cpp:125
void unload()
It forces the unload of the shared library from memory.
Definition: Library.cpp:169
Impl * m_pImpl
A pointer to the real implementation.
Definition: Library.h:179
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
static std::string getSearchPath()
It returns the system lookup path.
Definition: Library.cpp:267
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
~Library()
The destructor will automatically unload the library from memory.
Definition: Library.cpp:159
void load()
It loads the shared library to memory.
Definition: Library.cpp:164
TECOMMONEXPORT const std::string GetLastError()
It obtains the last thread's error message in a Windows System.
Definition: WinUtils.cpp:34
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
This class is designed for dealing with multi-language text translation in TerraLib.
bool isLoaded() const
Definition: Library.cpp:115
void * getAddress(const std::string &symbol) const
It returns the address where the given symbol is loaded into memory.
Definition: Library.cpp:184
const std::string GetDlError()
It returns a human readable string describing the most recent error that occurred from dlopen()...
Definition: LinuxUtils.cpp:35
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
const std::string & getFileName() const
It returns the library file name as informed in the constructor.
Definition: Library.cpp:179
void * m_module
The handle for DLLs, SO or a DyLib.
Definition: Library.cpp:150
static void addSearchDir(const std::string &d)
It adds the informed dir to the path used by the operational system to lookup for shared libraries...
Definition: Library.cpp:207
Library(const std::string &fileName, bool delayLoad=false)
Loads a new library specified by the file name.
Definition: Library.cpp:153
const std::string & getFileName() const
Definition: Library.cpp:120
std::string m_fileName
The library file name with full path.
Definition: Library.cpp:149