1 : /******************************************************************************
2 : * $Id: gdaldrivermanager.cpp 16573 2009-03-14 12:34:17Z rouault $
3 : *
4 : * Project: GDAL Core
5 : * Purpose: Implementation of GDALDriverManager class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1998, Frank Warmerdam
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "gdal_priv.h"
31 : #include "cpl_string.h"
32 : #include "cpl_multiproc.h"
33 : #include "ogr_srs_api.h"
34 : #include "cpl_multiproc.h"
35 : #include "gdal_pam.h"
36 :
37 : CPL_CVSID("$Id: gdaldrivermanager.cpp 16573 2009-03-14 12:34:17Z rouault $");
38 :
39 : static const char *pszUpdatableINST_DATA =
40 : "__INST_DATA_TARGET: ";
41 :
42 : /************************************************************************/
43 : /* ==================================================================== */
44 : /* GDALDriverManager */
45 : /* ==================================================================== */
46 : /************************************************************************/
47 :
48 : static volatile GDALDriverManager *poDM = NULL;
49 : static void *hDMMutex = NULL;
50 :
51 : /************************************************************************/
52 : /* GetGDALDriverManager() */
53 : /* */
54 : /* A freestanding function to get the only instance of the */
55 : /* GDALDriverManager. */
56 : /************************************************************************/
57 :
58 : /**
59 : * \brief Fetch the global GDAL driver manager.
60 : *
61 : * This function fetches the pointer to the singleton global driver manager.
62 : * If the driver manager doesn't exist it is automatically created.
63 : *
64 : * @return pointer to the global driver manager. This should not be able
65 : * to fail.
66 : */
67 :
68 86436 : GDALDriverManager * GetGDALDriverManager()
69 :
70 : {
71 86436 : if( poDM == NULL )
72 : {
73 336 : CPLMutexHolderD( &hDMMutex );
74 :
75 336 : if( poDM == NULL )
76 336 : poDM = new GDALDriverManager();
77 : }
78 :
79 : CPLAssert( NULL != poDM );
80 :
81 86436 : return const_cast<GDALDriverManager *>( poDM );
82 : }
83 :
84 : /************************************************************************/
85 : /* GDALDriverManager() */
86 : /************************************************************************/
87 :
88 336 : GDALDriverManager::GDALDriverManager()
89 :
90 : {
91 336 : nDrivers = 0;
92 336 : papoDrivers = NULL;
93 336 : pszHome = CPLStrdup("");
94 :
95 : CPLAssert( poDM == NULL );
96 :
97 : /* -------------------------------------------------------------------- */
98 : /* We want to push a location to search for data files */
99 : /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */
100 : /* files, and so forth. The static pszUpdateableINST_DATA */
101 : /* string can be updated within the shared library or */
102 : /* executable during an install to point installed data */
103 : /* directory. If it isn't burned in here then we use the */
104 : /* INST_DATA macro (setup at configure time) if */
105 : /* available. Otherwise we don't push anything and we hope */
106 : /* other mechanisms such as environment variables will have */
107 : /* been employed. */
108 : /* -------------------------------------------------------------------- */
109 336 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
110 : {
111 : // this one is picked up automatically by finder initialization.
112 : }
113 0 : else if( pszUpdatableINST_DATA[19] != ' ' )
114 : {
115 0 : CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
116 : }
117 : else
118 : {
119 : #ifdef INST_DATA
120 0 : CPLPushFinderLocation( INST_DATA );
121 : #endif
122 : }
123 336 : }
124 :
125 : /************************************************************************/
126 : /* ~GDALDriverManager() */
127 : /* */
128 : /* Eventually this should also likely clean up all open */
129 : /* datasets. Or perhaps the drivers that own them should do */
130 : /* that in their destructor? */
131 : /************************************************************************/
132 :
133 650 : GDALDriverManager::~GDALDriverManager()
134 :
135 : {
136 : /* -------------------------------------------------------------------- */
137 : /* Destroy the existing drivers. */
138 : /* -------------------------------------------------------------------- */
139 33475 : while( GetDriverCount() > 0 )
140 : {
141 32825 : GDALDriver *poDriver = GetDriver(0);
142 :
143 32825 : DeregisterDriver(poDriver);
144 32825 : delete poDriver;
145 : }
146 :
147 : /* -------------------------------------------------------------------- */
148 : /* Cleanup local memory. */
149 : /* -------------------------------------------------------------------- */
150 325 : VSIFree( papoDrivers );
151 325 : VSIFree( pszHome );
152 :
153 : /* -------------------------------------------------------------------- */
154 : /* Cleanup any Proxy related memory. */
155 : /* -------------------------------------------------------------------- */
156 325 : PamCleanProxyDB();
157 :
158 : /* -------------------------------------------------------------------- */
159 : /* Blow away all the finder hints paths. We really shouldn't */
160 : /* be doing all of them, but it is currently hard to keep track */
161 : /* of those that actually belong to us. */
162 : /* -------------------------------------------------------------------- */
163 325 : CPLFinderClean();
164 325 : CPLFreeConfig();
165 :
166 : /* -------------------------------------------------------------------- */
167 : /* Cleanup any memory allocated by the OGRSpatialReference */
168 : /* related subsystem. */
169 : /* -------------------------------------------------------------------- */
170 325 : OSRCleanup();
171 :
172 : /* -------------------------------------------------------------------- */
173 : /* Cleanup VSIFileManager. */
174 : /* -------------------------------------------------------------------- */
175 325 : VSICleanupFileManager();
176 :
177 : /* -------------------------------------------------------------------- */
178 : /* Cleanup thread local storage ... I hope the program is all */
179 : /* done with GDAL/OGR! */
180 : /* -------------------------------------------------------------------- */
181 325 : CPLCleanupTLS();
182 :
183 : /* -------------------------------------------------------------------- */
184 : /* Ensure the global driver manager pointer is NULLed out. */
185 : /* -------------------------------------------------------------------- */
186 325 : if( poDM == this )
187 325 : poDM = NULL;
188 650 : }
189 :
190 : /************************************************************************/
191 : /* GetDriverCount() */
192 : /************************************************************************/
193 :
194 : /**
195 : * \brief Fetch the number of registered drivers.
196 : *
197 : * This C analog to this is GDALGetDriverCount().
198 : *
199 : * @return the number of registered drivers.
200 : */
201 :
202 973445 : int GDALDriverManager::GetDriverCount()
203 :
204 : {
205 973445 : return( nDrivers );
206 : }
207 :
208 : /************************************************************************/
209 : /* GDALGetDriverCount() */
210 : /************************************************************************/
211 :
212 : /**
213 : * \brief Fetch the number of registered drivers.
214 : *
215 : * @see GDALDriverManager::GetDriverCount()
216 : */
217 :
218 18 : int CPL_STDCALL GDALGetDriverCount()
219 :
220 : {
221 18 : return GetGDALDriverManager()->GetDriverCount();
222 : }
223 :
224 : /************************************************************************/
225 : /* GetDriver() */
226 : /************************************************************************/
227 :
228 : /**
229 : * \brief Fetch driver by index.
230 : *
231 : * This C analog to this is GDALGetDriver().
232 : *
233 : * @param iDriver the driver index from 0 to GetDriverCount()-1.
234 : *
235 : * @return the driver identified by the index or NULL if the index is invalid
236 : */
237 :
238 966568 : GDALDriver * GDALDriverManager::GetDriver( int iDriver )
239 :
240 : {
241 966568 : CPLMutexHolderD( &hDMMutex );
242 :
243 966568 : if( iDriver < 0 || iDriver >= nDrivers )
244 0 : return NULL;
245 : else
246 966568 : return papoDrivers[iDriver];
247 : }
248 :
249 : /************************************************************************/
250 : /* GDALGetDriver() */
251 : /************************************************************************/
252 :
253 : /**
254 : * \brief Fetch driver by index.
255 : *
256 : * @see GDALDriverManager::GetDriver()
257 : */
258 :
259 1734 : GDALDriverH CPL_STDCALL GDALGetDriver( int iDriver )
260 :
261 : {
262 1734 : return (GDALDriverH) GetGDALDriverManager()->GetDriver(iDriver);
263 : }
264 :
265 : /************************************************************************/
266 : /* RegisterDriver() */
267 : /************************************************************************/
268 :
269 : /**
270 : * \brief Register a driver for use.
271 : *
272 : * The C analog is GDALRegisterDriver().
273 : *
274 : * Normally this method is used by format specific C callable registration
275 : * entry points such as GDALRegister_GTiff() rather than being called
276 : * directly by application level code.
277 : *
278 : * If this driver (based on the object pointer, not short name) is already
279 : * registered, then no change is made, and the index of the existing driver
280 : * is returned. Otherwise the driver list is extended, and the new driver
281 : * is added at the end.
282 : *
283 : * @param poDriver the driver to register.
284 : *
285 : * @return the index of the new installed driver.
286 : */
287 :
288 33974 : int GDALDriverManager::RegisterDriver( GDALDriver * poDriver )
289 :
290 : {
291 33974 : CPLMutexHolderD( &hDMMutex );
292 :
293 : /* -------------------------------------------------------------------- */
294 : /* If it is already registered, just return the existing */
295 : /* index. */
296 : /* -------------------------------------------------------------------- */
297 33974 : if( GetDriverByName( poDriver->GetDescription() ) != NULL )
298 : {
299 : int i;
300 :
301 0 : for( i = 0; i < nDrivers; i++ )
302 : {
303 0 : if( papoDrivers[i] == poDriver )
304 : {
305 0 : return i;
306 : }
307 : }
308 :
309 : CPLAssert( FALSE );
310 : }
311 :
312 : /* -------------------------------------------------------------------- */
313 : /* Otherwise grow the list to hold the new entry. */
314 : /* -------------------------------------------------------------------- */
315 : papoDrivers = (GDALDriver **)
316 33974 : VSIRealloc(papoDrivers, sizeof(GDALDriver *) * (nDrivers+1));
317 :
318 33974 : papoDrivers[nDrivers] = poDriver;
319 33974 : nDrivers++;
320 :
321 33974 : if( poDriver->pfnCreate != NULL )
322 10091 : poDriver->SetMetadataItem( GDAL_DCAP_CREATE, "YES" );
323 :
324 33974 : if( poDriver->pfnCreateCopy != NULL )
325 10439 : poDriver->SetMetadataItem( GDAL_DCAP_CREATECOPY, "YES" );
326 :
327 33974 : int iResult = nDrivers - 1;
328 :
329 33974 : return iResult;
330 : }
331 :
332 : /************************************************************************/
333 : /* GDALRegisterDriver() */
334 : /************************************************************************/
335 :
336 : /**
337 : * \brief Register a driver for use.
338 : *
339 : * @see GDALDriverManager::GetRegisterDriver()
340 : */
341 :
342 37 : int CPL_STDCALL GDALRegisterDriver( GDALDriverH hDriver )
343 :
344 : {
345 37 : VALIDATE_POINTER1( hDriver, "GDALRegisterDriver", 0 );
346 :
347 37 : return GetGDALDriverManager()->RegisterDriver( (GDALDriver *) hDriver );
348 : }
349 :
350 :
351 : /************************************************************************/
352 : /* DeregisterDriver() */
353 : /************************************************************************/
354 :
355 : /**
356 : * \brief Deregister the passed driver.
357 : *
358 : * If the driver isn't found no change is made.
359 : *
360 : * The C analog is GDALDeregisterDriver().
361 : *
362 : * @param poDriver the driver to deregister.
363 : */
364 :
365 32862 : void GDALDriverManager::DeregisterDriver( GDALDriver * poDriver )
366 :
367 : {
368 : int i;
369 32862 : CPLMutexHolderD( &hDMMutex );
370 :
371 36231 : for( i = 0; i < nDrivers; i++ )
372 : {
373 36231 : if( papoDrivers[i] == poDriver )
374 32862 : break;
375 : }
376 :
377 32862 : if( i == nDrivers )
378 : return;
379 :
380 1707325 : while( i < nDrivers-1 )
381 : {
382 1641601 : papoDrivers[i] = papoDrivers[i+1];
383 1641601 : i++;
384 : }
385 32862 : nDrivers--;
386 : }
387 :
388 : /************************************************************************/
389 : /* GDALDeregisterDriver() */
390 : /************************************************************************/
391 :
392 : /**
393 : * \brief Deregister the passed driver.
394 : *
395 : * @see GDALDriverManager::GetDeregisterDriver()
396 : */
397 :
398 37 : void CPL_STDCALL GDALDeregisterDriver( GDALDriverH hDriver )
399 :
400 : {
401 37 : VALIDATE_POINTER0( hDriver, "GDALDeregisterDriver" );
402 :
403 37 : GetGDALDriverManager()->DeregisterDriver( (GDALDriver *) hDriver );
404 : }
405 :
406 :
407 : /************************************************************************/
408 : /* GetDriverByName() */
409 : /************************************************************************/
410 :
411 : /**
412 : * \brief Fetch a driver based on the short name.
413 : *
414 : * The C analog is the GDALGetDriverByName() function.
415 : *
416 : * @param pszName the short name, such as GTiff, being searched for.
417 : *
418 : * @return the identified driver, or NULL if no match is found.
419 : */
420 :
421 70610 : GDALDriver * GDALDriverManager::GetDriverByName( const char * pszName )
422 :
423 : {
424 : int i;
425 :
426 70610 : CPLMutexHolderD( &hDMMutex );
427 :
428 3539398 : for( i = 0; i < nDrivers; i++ )
429 : {
430 3471460 : if( EQUAL(papoDrivers[i]->GetDescription(), pszName) )
431 2672 : return papoDrivers[i];
432 : }
433 :
434 67938 : return NULL;
435 : }
436 :
437 : /************************************************************************/
438 : /* GDALGetDriverByName() */
439 : /************************************************************************/
440 :
441 : /**
442 : * \brief Fetch a driver based on the short name.
443 : *
444 : * @see GDALDriverManager::GetDriverByName()
445 : */
446 :
447 36623 : GDALDriverH CPL_STDCALL GDALGetDriverByName( const char * pszName )
448 :
449 : {
450 36623 : VALIDATE_POINTER1( pszName, "GDALGetDriverByName", NULL );
451 :
452 36623 : return( GetGDALDriverManager()->GetDriverByName( pszName ) );
453 : }
454 :
455 : /************************************************************************/
456 : /* GetHome() */
457 : /************************************************************************/
458 :
459 338 : const char *GDALDriverManager::GetHome()
460 :
461 : {
462 338 : return pszHome;
463 : }
464 :
465 : /************************************************************************/
466 : /* SetHome() */
467 : /************************************************************************/
468 :
469 0 : void GDALDriverManager::SetHome( const char * pszNewHome )
470 :
471 : {
472 0 : CPLMutexHolderD( &hDMMutex );
473 :
474 0 : CPLFree( pszHome );
475 0 : pszHome = CPLStrdup(pszNewHome);
476 0 : }
477 :
478 : /************************************************************************/
479 : /* AutoSkipDrivers() */
480 : /************************************************************************/
481 :
482 : /**
483 : * \brief This method unload undesirable drivers.
484 : *
485 : * All drivers specified in the space delimited list in the GDAL_SKIP
486 : * environmentvariable) will be deregistered and destroyed. This method
487 : * should normally be called after registration of standard drivers to allow
488 : * the user a way of unloading undesired drivers. The GDALAllRegister()
489 : * function already invokes AutoSkipDrivers() at the end, so if that functions
490 : * is called, it should not be necessary to call this method from application
491 : * code.
492 : */
493 :
494 338 : void GDALDriverManager::AutoSkipDrivers()
495 :
496 : {
497 338 : if( CPLGetConfigOption( "GDAL_SKIP", NULL ) == NULL )
498 338 : return;
499 :
500 0 : char **papszList = CSLTokenizeString( CPLGetConfigOption("GDAL_SKIP","") );
501 :
502 0 : for( int i = 0; i < CSLCount(papszList); i++ )
503 : {
504 0 : GDALDriver *poDriver = GetDriverByName( papszList[i] );
505 :
506 0 : if( poDriver == NULL )
507 : CPLError( CE_Warning, CPLE_AppDefined,
508 : "Unable to find driver %s to unload from GDAL_SKIP environment variable.",
509 0 : papszList[i] );
510 : else
511 : {
512 0 : CPLDebug( "GDAL", "AutoSkipDriver(%s)", papszList[i] );
513 0 : DeregisterDriver( poDriver );
514 0 : delete poDriver;
515 : }
516 : }
517 :
518 0 : CSLDestroy( papszList );
519 : }
520 :
521 : /************************************************************************/
522 : /* AutoLoadDrivers() */
523 : /************************************************************************/
524 :
525 : /**
526 : * \brief Auto-load GDAL drivers from shared libraries.
527 : *
528 : * This function will automatically load drivers from shared libraries. It
529 : * searches the "driver path" for .so (or .dll) files that start with the
530 : * prefix "gdal_X.so". It then tries to load them and then tries to call a
531 : * function within them called GDALRegister_X() where the 'X' is the same as
532 : * the remainder of the shared library basename ('X' is case sensitive), or
533 : * failing that to call GDALRegisterMe().
534 : *
535 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
536 : * environment variable it set, it is taken to be a list of directories to
537 : * search separated by colons on UNIX, or semi-colons on Windows. Otherwise
538 : * the /usr/local/lib/gdalplugins directory, and (if known) the
539 : * lib/gdalplugins subdirectory of the gdal home directory are searched on
540 : * UNIX and $(BINDIR)\gdalplugins on Windows.
541 : */
542 :
543 338 : void GDALDriverManager::AutoLoadDrivers()
544 :
545 : {
546 338 : char **papszSearchPath = NULL;
547 : const char *pszGDAL_DRIVER_PATH =
548 338 : CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
549 :
550 : /* -------------------------------------------------------------------- */
551 : /* Where should we look for stuff? */
552 : /* -------------------------------------------------------------------- */
553 338 : if( pszGDAL_DRIVER_PATH != NULL )
554 : {
555 : #ifdef WIN32
556 : papszSearchPath =
557 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
558 : #else
559 : papszSearchPath =
560 0 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
561 : #endif
562 : }
563 : else
564 : {
565 : #ifdef GDAL_PREFIX
566 : papszSearchPath = CSLAddString( papszSearchPath,
567 : #ifdef MACOSX_FRAMEWORK
568 : GDAL_PREFIX "/PlugIns");
569 : #else
570 338 : GDAL_PREFIX "/lib/gdalplugins" );
571 : #endif
572 : #else
573 : char szExecPath[1024];
574 :
575 : if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
576 : {
577 : char szPluginDir[sizeof(szExecPath)+50];
578 : strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
579 : strcat( szPluginDir, "\\gdalplugins" );
580 : papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
581 : }
582 : else
583 : {
584 : papszSearchPath = CSLAddString( papszSearchPath,
585 : "/usr/local/lib/gdalplugins" );
586 : }
587 : #endif
588 :
589 : #ifdef MACOSX_FRAMEWORK
590 : papszSearchPath = CSLAddString( papszSearchPath,
591 : "/Library/Application Support/GDAL/PlugIns" );
592 : #endif
593 :
594 :
595 338 : if( strlen(GetHome()) > 0 )
596 : {
597 : papszSearchPath = CSLAddString( papszSearchPath,
598 : CPLFormFilename( GetHome(),
599 : #ifdef MACOSX_FRAMEWORK
600 : "Library/Application Support/GDAL/PlugIns", NULL ) );
601 : #else
602 0 : "lib/gdalplugins", NULL ) );
603 : #endif
604 : }
605 : }
606 :
607 : /* -------------------------------------------------------------------- */
608 : /* Scan each directory looking for files starting with gdal_ */
609 : /* -------------------------------------------------------------------- */
610 676 : for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
611 : {
612 338 : char **papszFiles = CPLReadDir( papszSearchPath[iDir] );
613 :
614 338 : for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
615 : {
616 : char *pszFuncName;
617 : const char *pszFilename;
618 0 : const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
619 : void *pRegister;
620 :
621 0 : if( !EQUALN(papszFiles[iFile],"gdal_",5) )
622 0 : continue;
623 :
624 0 : if( !EQUAL(pszExtension,"dll")
625 : && !EQUAL(pszExtension,"so")
626 : && !EQUAL(pszExtension,"dylib") )
627 0 : continue;
628 :
629 0 : pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
630 : sprintf( pszFuncName, "GDALRegister_%s",
631 0 : CPLGetBasename(papszFiles[iFile]) + 5 );
632 :
633 : pszFilename =
634 0 : CPLFormFilename( papszSearchPath[iDir],
635 0 : papszFiles[iFile], NULL );
636 :
637 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
638 0 : if( pRegister == NULL )
639 : {
640 0 : strcpy( pszFuncName, "GDALRegisterMe" );
641 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
642 : }
643 :
644 0 : if( pRegister != NULL )
645 : {
646 : CPLDebug( "GDAL", "Auto register %s using %s.",
647 0 : pszFilename, pszFuncName );
648 :
649 0 : ((void (*)()) pRegister)();
650 : }
651 :
652 0 : CPLFree( pszFuncName );
653 : }
654 :
655 338 : CSLDestroy( papszFiles );
656 : }
657 :
658 338 : CSLDestroy( papszSearchPath );
659 338 : }
660 :
661 : /************************************************************************/
662 : /* GDALDestroyDriverManager() */
663 : /************************************************************************/
664 :
665 : /**
666 : * \brief Destroy the driver manager.
667 : *
668 : * Incidently unloads all managed drivers.
669 : *
670 : * NOTE: This function is not thread safe. It should not be called while
671 : * other threads are actively using GDAL.
672 : */
673 :
674 325 : void CPL_STDCALL GDALDestroyDriverManager( void )
675 :
676 : {
677 : // THREADSAFETY: We would like to lock the mutex here, but it
678 : // needs to be reacquired within the destructor during driver
679 : // deregistration.
680 325 : if( poDM != NULL )
681 325 : delete poDM;
682 325 : }
683 :
684 :
|