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