1 : /******************************************************************************
2 : * $Id: ogrsfdriverregistrar.cpp 18462 2010-01-07 19:31:11Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: The OGRSFDriverRegistrar class implementation.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 1999, Les Technologies SoftMap Inc.
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 "ogrsf_frmts.h"
31 : #include "ogr_api.h"
32 : #include "ogr_p.h"
33 : #include "cpl_multiproc.h"
34 :
35 : CPL_CVSID("$Id: ogrsfdriverregistrar.cpp 18462 2010-01-07 19:31:11Z rouault $");
36 :
37 : static void *hDRMutex = NULL;
38 : static OGRSFDriverRegistrar * volatile poRegistrar = NULL;
39 :
40 : static const char *pszUpdatableINST_DATA =
41 : "__INST_DATA_TARGET: ";
42 : /************************************************************************/
43 : /* OGRSFDriverRegistrar */
44 : /************************************************************************/
45 :
46 : /**
47 : * \brief Constructor
48 : *
49 : * Normally the driver registrar is constucted by the
50 : * OGRSFDriverRegistrar::GetRegistrar() accessor which ensures singleton
51 : * status.
52 : */
53 :
54 64 : OGRSFDriverRegistrar::OGRSFDriverRegistrar()
55 :
56 : {
57 : CPLAssert( poRegistrar == NULL );
58 64 : nDrivers = 0;
59 64 : papoDrivers = NULL;
60 :
61 64 : nOpenDSCount = 0;
62 64 : papszOpenDSRawName = NULL;
63 64 : papoOpenDS = NULL;
64 64 : papoOpenDSDriver = NULL;
65 64 : panOpenDSPID = NULL;
66 :
67 : /* -------------------------------------------------------------------- */
68 : /* We want to push a location to search for data files */
69 : /* supporting GDAL/OGR such as EPSG csv files, S-57 definition */
70 : /* files, and so forth. The static pszUpdateableINST_DATA */
71 : /* string can be updated within the shared library or */
72 : /* executable during an install to point installed data */
73 : /* directory. If it isn't burned in here then we use the */
74 : /* INST_DATA macro (setup at configure time) if */
75 : /* available. Otherwise we don't push anything and we hope */
76 : /* other mechanisms such as environment variables will have */
77 : /* been employed. */
78 : /* -------------------------------------------------------------------- */
79 64 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
80 : {
81 64 : CPLPushFinderLocation( CPLGetConfigOption( "GDAL_DATA", NULL ) );
82 : }
83 0 : else if( pszUpdatableINST_DATA[19] != ' ' )
84 : {
85 0 : CPLPushFinderLocation( pszUpdatableINST_DATA + 19 );
86 : }
87 : else
88 : {
89 : #ifdef INST_DATA
90 0 : CPLPushFinderLocation( INST_DATA );
91 : #endif
92 : }
93 64 : }
94 :
95 : /************************************************************************/
96 : /* ~OGRSFDriverRegistrar() */
97 : /************************************************************************/
98 :
99 48 : OGRSFDriverRegistrar::~OGRSFDriverRegistrar()
100 :
101 : {
102 1488 : for( int i = 0; i < nDrivers; i++ )
103 : {
104 1440 : delete papoDrivers[i];
105 : }
106 :
107 48 : CPLFree( papoDrivers );
108 48 : papoDrivers = NULL;
109 :
110 48 : poRegistrar = NULL;
111 48 : }
112 :
113 : /************************************************************************/
114 : /* OGRCleanupAll() */
115 : /************************************************************************/
116 :
117 : /**
118 : * \brief Cleanup all OGR related resources.
119 : *
120 : * This function will destroy the OGRSFDriverRegistrar along with all registered
121 : * drivers, and then cleanup long lived OSR (OGRSpatialReference) and CPL
122 : * resources. This may be called in an application when OGR services are
123 : * no longer needed. It is not normally required, but by freeing all
124 : * dynamically allocated memory it can make memory leak testing easier.
125 : *
126 : * In addition to destroying the OGRDriverRegistrar, this function also calls:
127 : * - OSRCleanup()
128 : * - CPLFinderClean()
129 : * - VSICleanupFileManager()
130 : * - CPLFreeConfig()
131 : * - CPLCleanupTLS()
132 : */
133 292 : void OGRCleanupAll()
134 :
135 : {
136 : {
137 : // We don't want to hold the mutex while CPL level mutex services
138 : // are being destroyed ... just long enough to avoid conflict while
139 : // cleaning up OGR and OSR services.
140 292 : CPLMutexHolderD( &hDRMutex );
141 :
142 292 : if( poRegistrar != NULL )
143 48 : delete poRegistrar;
144 292 : OSRCleanup();
145 : }
146 :
147 292 : CPLFinderClean();
148 292 : VSICleanupFileManager();
149 292 : CPLFreeConfig();
150 292 : CPLCleanupTLS();
151 292 : }
152 :
153 :
154 : /************************************************************************/
155 : /* GetRegistrar() */
156 : /************************************************************************/
157 :
158 : /**
159 : * \brief Fetch registrar.
160 : *
161 : * This static method should be used to fetch the singleton
162 : * registrar. It will create a registrar if there is not already
163 : * one in existance.
164 : *
165 : * @return the current driver registrar.
166 : */
167 :
168 3039 : OGRSFDriverRegistrar *OGRSFDriverRegistrar::GetRegistrar()
169 :
170 : {
171 3039 : if( poRegistrar == NULL )
172 : {
173 64 : CPLMutexHolderD( &hDRMutex );
174 :
175 64 : if( poRegistrar == NULL )
176 64 : poRegistrar = new OGRSFDriverRegistrar();
177 : }
178 :
179 : CPLAssert( NULL != poRegistrar );
180 3039 : return poRegistrar;
181 : }
182 :
183 : /************************************************************************/
184 : /* Open() */
185 : /************************************************************************/
186 :
187 336 : OGRDataSource *OGRSFDriverRegistrar::Open( const char * pszName,
188 : int bUpdate,
189 : OGRSFDriver ** ppoDriver )
190 :
191 : {
192 : OGRDataSource *poDS;
193 :
194 336 : if( ppoDriver != NULL )
195 22 : *ppoDriver = NULL;
196 :
197 336 : GetRegistrar();
198 :
199 336 : CPLErrorReset();
200 :
201 336 : CPLAcquireMutex( hDRMutex, 0.1 );
202 :
203 3492 : for( int iDriver = 0; iDriver < poRegistrar->nDrivers; iDriver++ )
204 : {
205 3488 : OGRSFDriver *poDriver = poRegistrar->papoDrivers[iDriver];
206 :
207 3488 : CPLReleaseMutex( hDRMutex );
208 :
209 3488 : poDS = poDriver->Open( pszName, bUpdate );
210 3488 : if( poDS != NULL )
211 : {
212 331 : if( ppoDriver != NULL )
213 22 : *ppoDriver = poDriver;
214 :
215 331 : poDS->Reference();
216 331 : if( poDS->GetDriver() == NULL )
217 331 : poDS->m_poDriver = poDriver;
218 :
219 : CPLDebug( "OGR", "OGROpen(%s/%p) succeeded as %s.",
220 331 : pszName, poDS, poDS->GetDriver()->GetName() );
221 :
222 331 : return poDS;
223 : }
224 :
225 3157 : if( CPLGetLastErrorType() == CE_Failure )
226 1 : return NULL;
227 :
228 3156 : CPLAcquireMutex( hDRMutex, 0.1 );
229 : }
230 :
231 4 : CPLReleaseMutex( hDRMutex );
232 :
233 4 : CPLDebug( "OGR", "OGROpen(%s) failed.", pszName );
234 :
235 4 : return NULL;
236 : }
237 :
238 : /************************************************************************/
239 : /* OGROpen() */
240 : /************************************************************************/
241 :
242 260 : OGRDataSourceH OGROpen( const char *pszName, int bUpdate,
243 : OGRSFDriverH *pahDriverList )
244 :
245 : {
246 260 : VALIDATE_POINTER1( pszName, "OGROpen", NULL );
247 :
248 260 : if (poRegistrar)
249 : return (OGRDataSourceH)
250 : poRegistrar->Open( pszName, bUpdate,
251 260 : (OGRSFDriver **) pahDriverList );
252 :
253 0 : return NULL;
254 : }
255 :
256 : /************************************************************************/
257 : /* OpenShared() */
258 : /************************************************************************/
259 :
260 : OGRDataSource *
261 22 : OGRSFDriverRegistrar::OpenShared( const char * pszName, int bUpdate,
262 : OGRSFDriver ** ppoDriver )
263 :
264 : {
265 : OGRDataSource *poDS;
266 :
267 22 : if( ppoDriver != NULL )
268 0 : *ppoDriver = NULL;
269 :
270 22 : CPLErrorReset();
271 :
272 : /* -------------------------------------------------------------------- */
273 : /* First try finding an existing open dataset matching exactly */
274 : /* on the original datasource raw name used to open the */
275 : /* datasource. */
276 : /* */
277 : /* NOTE: It is an error, but currently we ignore the bUpdate, */
278 : /* and return whatever is open even if it is read-only and the */
279 : /* application requested update access. */
280 : /* -------------------------------------------------------------------- */
281 : {
282 : int iDS;
283 22 : CPLMutexHolderD( &hDRMutex );
284 22 : GIntBig nThisPID = CPLGetPID();
285 :
286 31 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
287 : {
288 23 : poDS = papoOpenDS[iDS];
289 :
290 37 : if( strcmp( pszName, papszOpenDSRawName[iDS]) == 0
291 14 : && nThisPID == panOpenDSPID[iDS] )
292 : {
293 14 : poDS->Reference();
294 :
295 14 : if( ppoDriver != NULL )
296 0 : *ppoDriver = papoOpenDSDriver[iDS];
297 14 : return poDS;
298 : }
299 : }
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* If that doesn't match, try matching on the name returned by */
303 : /* the datasource itself. */
304 : /* -------------------------------------------------------------------- */
305 11 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
306 : {
307 3 : poDS = papoOpenDS[iDS];
308 :
309 3 : if( strcmp( pszName, poDS->GetName()) == 0
310 0 : && nThisPID == panOpenDSPID[iDS] )
311 : {
312 0 : poDS->Reference();
313 :
314 0 : if( ppoDriver != NULL )
315 0 : *ppoDriver = papoOpenDSDriver[iDS];
316 0 : return poDS;
317 : }
318 0 : }
319 : }
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* We don't have the datasource. Open it normally. */
323 : /* -------------------------------------------------------------------- */
324 8 : OGRSFDriver *poTempDriver = NULL;
325 :
326 8 : poDS = Open( pszName, bUpdate, &poTempDriver );
327 :
328 8 : if( poDS == NULL )
329 0 : return poDS;
330 :
331 : /* -------------------------------------------------------------------- */
332 : /* We don't have this datasource already. Grow our list to */
333 : /* hold the new datasource. */
334 : /* -------------------------------------------------------------------- */
335 : {
336 8 : CPLMutexHolderD( &hDRMutex );
337 :
338 : papszOpenDSRawName = (char **)
339 8 : CPLRealloc( papszOpenDSRawName, sizeof(char*) * (nOpenDSCount+1) );
340 :
341 : papoOpenDS = (OGRDataSource **)
342 8 : CPLRealloc( papoOpenDS, sizeof(char*) * (nOpenDSCount+1) );
343 :
344 : papoOpenDSDriver = (OGRSFDriver **)
345 8 : CPLRealloc( papoOpenDSDriver, sizeof(char*) * (nOpenDSCount+1) );
346 :
347 : panOpenDSPID = (GIntBig *)
348 8 : CPLRealloc( panOpenDSPID, sizeof(GIntBig) * (nOpenDSCount+1) );
349 :
350 8 : papszOpenDSRawName[nOpenDSCount] = CPLStrdup( pszName );
351 8 : papoOpenDS[nOpenDSCount] = poDS;
352 8 : papoOpenDSDriver[nOpenDSCount] = poTempDriver;
353 8 : panOpenDSPID[nOpenDSCount] = CPLGetPID();
354 :
355 8 : nOpenDSCount++;
356 : }
357 :
358 8 : if( ppoDriver != NULL )
359 0 : *ppoDriver = poTempDriver;
360 :
361 8 : return poDS;
362 : }
363 :
364 : /************************************************************************/
365 : /* OGROpenShared() */
366 : /************************************************************************/
367 :
368 15 : OGRDataSourceH OGROpenShared( const char *pszName, int bUpdate,
369 : OGRSFDriverH *pahDriverList )
370 :
371 : {
372 15 : VALIDATE_POINTER1( pszName, "OGROpenShared", NULL );
373 :
374 15 : OGRSFDriverRegistrar::GetRegistrar();
375 : return (OGRDataSourceH)
376 : poRegistrar->OpenShared( pszName, bUpdate,
377 15 : (OGRSFDriver **) pahDriverList );
378 : }
379 :
380 : /************************************************************************/
381 : /* ReleaseDataSource() */
382 : /************************************************************************/
383 :
384 384 : OGRErr OGRSFDriverRegistrar::ReleaseDataSource( OGRDataSource * poDS )
385 :
386 : {
387 : {
388 384 : CPLMutexHolderD( &hDRMutex );
389 :
390 : int iDS;
391 :
392 404 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
393 : {
394 38 : if( poDS == papoOpenDS[iDS] )
395 18 : break;
396 : }
397 :
398 384 : if( iDS == nOpenDSCount )
399 : {
400 : CPLDebug( "OGR",
401 : "ReleaseDataSource(%s/%p) on unshared datasource!\n"
402 : "Deleting directly.",
403 366 : poDS->GetName(), poDS );
404 366 : delete poDS;
405 366 : return OGRERR_FAILURE;
406 : }
407 :
408 18 : if( poDS->GetRefCount() > 0 )
409 18 : poDS->Dereference();
410 :
411 18 : if( poDS->GetRefCount() > 0 )
412 : {
413 : CPLDebug( "OGR",
414 : "ReleaseDataSource(%s/%p) ... just dereferencing.",
415 10 : poDS->GetName(), poDS );
416 10 : return OGRERR_NONE;
417 : }
418 :
419 8 : if( poDS->GetSummaryRefCount() > 0 )
420 : {
421 : CPLDebug( "OGR",
422 : "OGRSFDriverRegistrar::ReleaseDataSource(%s)\n"
423 : "Datasource reference count is now zero, but some layers\n"
424 : "are still referenced ... not closing datasource.",
425 0 : poDS->GetName() );
426 0 : return OGRERR_FAILURE;
427 : }
428 :
429 : /* -------------------------------------------------------------------- */
430 : /* We really want to close this file, and remove it from the */
431 : /* shared list. */
432 : /* -------------------------------------------------------------------- */
433 : CPLDebug( "OGR",
434 : "ReleaseDataSource(%s/%p) dereferenced and now destroying.",
435 8 : poDS->GetName(), poDS );
436 :
437 8 : CPLFree( papszOpenDSRawName[iDS] );
438 : memmove( papszOpenDSRawName + iDS, papszOpenDSRawName + iDS + 1,
439 8 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
440 : memmove( papoOpenDS + iDS, papoOpenDS + iDS + 1,
441 8 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
442 : memmove( papoOpenDSDriver + iDS, papoOpenDSDriver + iDS + 1,
443 8 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
444 : memmove( panOpenDSPID + iDS, panOpenDSPID + iDS + 1,
445 8 : sizeof(GIntBig) * (nOpenDSCount - iDS - 1) );
446 :
447 8 : nOpenDSCount--;
448 :
449 8 : if( nOpenDSCount == 0 )
450 : {
451 5 : CPLFree( papszOpenDSRawName );
452 5 : papszOpenDSRawName = NULL;
453 5 : CPLFree( papoOpenDS );
454 5 : papoOpenDS = NULL;
455 5 : CPLFree( papoOpenDSDriver );
456 5 : papoOpenDSDriver = NULL;
457 5 : CPLFree( panOpenDSPID );
458 5 : panOpenDSPID = NULL;
459 0 : }
460 : }
461 :
462 : /* -------------------------------------------------------------------- */
463 : /* We are careful to only do the delete poDS after adjusting */
464 : /* the table, as if it is a virtual dataset, other removals may */
465 : /* happen in the meantime. We are also careful to do this */
466 : /* outside the mutex protected loop as destroying a dataset can */
467 : /* take quite a while. */
468 : /* -------------------------------------------------------------------- */
469 8 : delete poDS;
470 :
471 8 : return OGRERR_NONE;
472 : }
473 :
474 : /************************************************************************/
475 : /* OGRReleaseDataSource() */
476 : /************************************************************************/
477 :
478 373 : OGRErr OGRReleaseDataSource( OGRDataSourceH hDS )
479 :
480 : {
481 373 : VALIDATE_POINTER1( hDS, "OGRReleaseDataSource", OGRERR_INVALID_HANDLE );
482 :
483 373 : OGRSFDriverRegistrar::GetRegistrar();
484 373 : return poRegistrar->ReleaseDataSource((OGRDataSource *) hDS);
485 : }
486 :
487 : /************************************************************************/
488 : /* OGRGetOpenDSCount() */
489 : /************************************************************************/
490 :
491 5 : int OGRGetOpenDSCount()
492 :
493 : {
494 5 : OGRSFDriverRegistrar::GetRegistrar();
495 5 : return poRegistrar->GetOpenDSCount();
496 : }
497 :
498 : /************************************************************************/
499 : /* GetOpenDS() */
500 : /************************************************************************/
501 :
502 1 : OGRDataSource *OGRSFDriverRegistrar::GetOpenDS( int iDS )
503 :
504 : {
505 1 : CPLMutexHolderD( &hDRMutex );
506 :
507 1 : if( iDS < 0 || iDS >= nOpenDSCount )
508 0 : return NULL;
509 : else
510 1 : return papoOpenDS[iDS];
511 : }
512 :
513 : /************************************************************************/
514 : /* OGRGetOpenDS() */
515 : /************************************************************************/
516 :
517 1 : OGRDataSourceH OGRGetOpenDS( int iDS )
518 :
519 : {
520 1 : OGRSFDriverRegistrar::GetRegistrar();
521 1 : return (OGRDataSourceH) poRegistrar->GetOpenDS( iDS );
522 : }
523 :
524 : /************************************************************************/
525 : /* RegisterDriver() */
526 : /************************************************************************/
527 :
528 1920 : void OGRSFDriverRegistrar::RegisterDriver( OGRSFDriver * poDriver )
529 :
530 : {
531 1920 : CPLMutexHolderD( &hDRMutex );
532 : int iDriver;
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* It has no effect to register a driver more than once. */
536 : /* -------------------------------------------------------------------- */
537 29760 : for( iDriver = 0; iDriver < nDrivers; iDriver++ )
538 : {
539 27840 : if( poDriver == papoDrivers[iDriver] )
540 : return;
541 :
542 : /* Same name but different pointer. Likely a second call to OGRRegisterAll() */
543 : /* We delete the new driver */
544 27840 : if (EQUAL(poDriver->GetName(), papoDrivers[iDriver]->GetName()))
545 : {
546 0 : delete poDriver;
547 : return;
548 : }
549 : }
550 :
551 : /* -------------------------------------------------------------------- */
552 : /* Skip and destroy drivers in the black list. */
553 : /* -------------------------------------------------------------------- */
554 : char** papszSkipDrivers =
555 1920 : CSLTokenizeStringComplex(CPLGetConfigOption("OGR_SKIP", ""), ",", FALSE, FALSE);
556 1920 : char** iter = papszSkipDrivers;
557 3840 : while(*iter)
558 : {
559 0 : if (strcmp(*iter, poDriver->GetName()) == 0)
560 : {
561 0 : CSLDestroy(papszSkipDrivers);
562 0 : delete poDriver;
563 : return;
564 : }
565 0 : iter ++;
566 : }
567 1920 : CSLDestroy(papszSkipDrivers);
568 :
569 : /* -------------------------------------------------------------------- */
570 : /* Add to the end of the driver list. */
571 : /* -------------------------------------------------------------------- */
572 : papoDrivers = (OGRSFDriver **)
573 1920 : CPLRealloc( papoDrivers, (nDrivers+1) * sizeof(void*) );
574 :
575 1920 : papoDrivers[nDrivers++] = poDriver;
576 : }
577 :
578 : /************************************************************************/
579 : /* OGRRegisterDriver() */
580 : /************************************************************************/
581 :
582 0 : void OGRRegisterDriver( OGRSFDriverH hDriver )
583 :
584 : {
585 0 : VALIDATE_POINTER0( hDriver, "OGRRegisterDriver" );
586 :
587 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(
588 0 : (OGRSFDriver *) hDriver );
589 : }
590 :
591 : /************************************************************************/
592 : /* GetDriverCount() */
593 : /************************************************************************/
594 :
595 131 : int OGRSFDriverRegistrar::GetDriverCount()
596 :
597 : {
598 131 : return nDrivers;
599 : }
600 :
601 : /************************************************************************/
602 : /* OGRGetDriverCount() */
603 : /************************************************************************/
604 :
605 20 : int OGRGetDriverCount()
606 :
607 : {
608 20 : if (poRegistrar)
609 19 : return poRegistrar->GetDriverCount();
610 :
611 1 : return 0;
612 : }
613 :
614 : /************************************************************************/
615 : /* GetDriver() */
616 : /************************************************************************/
617 :
618 112 : OGRSFDriver *OGRSFDriverRegistrar::GetDriver( int iDriver )
619 :
620 : {
621 112 : CPLMutexHolderD( &hDRMutex );
622 :
623 112 : if( iDriver < 0 || iDriver >= nDrivers )
624 0 : return NULL;
625 : else
626 112 : return papoDrivers[iDriver];
627 : }
628 :
629 : /************************************************************************/
630 : /* OGRGetDriver() */
631 : /************************************************************************/
632 :
633 0 : OGRSFDriverH OGRGetDriver( int iDriver )
634 :
635 : {
636 0 : VALIDATE_POINTER1( poRegistrar, "OGRGetDriver", NULL );
637 :
638 0 : return (OGRSFDriverH) poRegistrar->GetDriver( iDriver );
639 : }
640 :
641 : /************************************************************************/
642 : /* GetDriverByName() */
643 : /************************************************************************/
644 :
645 179 : OGRSFDriver *OGRSFDriverRegistrar::GetDriverByName( const char * pszName )
646 :
647 : {
648 179 : CPLMutexHolderD( &hDRMutex );
649 :
650 1477 : for( int i = 0; i < nDrivers; i++ )
651 : {
652 4416 : if( papoDrivers[i] != NULL
653 2944 : && EQUAL(papoDrivers[i]->GetName(),pszName) )
654 174 : return papoDrivers[i];
655 : }
656 :
657 5 : return NULL;
658 : }
659 :
660 : /************************************************************************/
661 : /* OGRGetDriverByName() */
662 : /************************************************************************/
663 :
664 179 : OGRSFDriverH OGRGetDriverByName( const char *pszName )
665 :
666 : {
667 179 : VALIDATE_POINTER1( pszName, "OGRGetDriverByName", NULL );
668 :
669 : return (OGRSFDriverH)
670 179 : OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( pszName );
671 : }
672 :
673 : /************************************************************************/
674 : /* AutoLoadDrivers() */
675 : /************************************************************************/
676 :
677 : /**
678 : * \brief Auto-load GDAL drivers from shared libraries.
679 : *
680 : * This function will automatically load drivers from shared libraries. It
681 : * searches the "driver path" for .so (or .dll) files that start with the
682 : * prefix "ogr_X.so". It then tries to load them and then tries to call
683 : * a function within them called RegisterOGRX() where the 'X' is the same
684 : * as the remainder of the shared library basename, or failing that to
685 : * call GDALRegisterMe().
686 : *
687 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
688 : * environment variable it set, it is taken to be a list of directories to
689 : * search separated by colons on unix, or semi-colons on Windows.
690 : *
691 : * If that is not set the following defaults are used:
692 : *
693 : * <ul>
694 : * <li> Linux/Unix: <prefix>/lib/gdalplugins is searched or
695 : * /usr/local/lib/gdalplugins if the install prefix is not known.
696 : * <li> MacOSX: <prefix>/PlugIns is searched, or /usr/local/lib/gdalplugins if
697 : * the install prefix is not known. Also, the framework directory
698 : * /Library/Application Support/GDAL/PlugIns is searched.
699 : * <li> Win32: <prefix>/lib/gdalplugins if the prefix is known (normally it
700 : * is not), otherwise the gdalplugins subdirectory of the directory containing
701 : * the currently running executable is used.
702 : * </ul>
703 : */
704 :
705 64 : void OGRSFDriverRegistrar::AutoLoadDrivers()
706 :
707 : {
708 64 : char **papszSearchPath = NULL;
709 : const char *pszGDAL_DRIVER_PATH =
710 64 : CPLGetConfigOption( "OGR_DRIVER_PATH", NULL );
711 :
712 64 : if( pszGDAL_DRIVER_PATH == NULL )
713 : pszGDAL_DRIVER_PATH =
714 64 : CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
715 :
716 : /* -------------------------------------------------------------------- */
717 : /* Where should we look for stuff? */
718 : /* -------------------------------------------------------------------- */
719 64 : if( pszGDAL_DRIVER_PATH != NULL )
720 : {
721 : #ifdef WIN32
722 : papszSearchPath =
723 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
724 : #else
725 : papszSearchPath =
726 0 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
727 : #endif
728 : }
729 : else
730 : {
731 : #ifdef GDAL_PREFIX
732 : papszSearchPath = CSLAddString( papszSearchPath,
733 : #ifdef MACOSX_FRAMEWORK
734 : GDAL_PREFIX "/PlugIns");
735 : #else
736 64 : GDAL_PREFIX "/lib/gdalplugins" );
737 : #endif
738 : #else
739 : char szExecPath[1024];
740 :
741 : if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
742 : {
743 : char szPluginDir[sizeof(szExecPath)+50];
744 : strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
745 : strcat( szPluginDir, "\\gdalplugins\\" );
746 : papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
747 : }
748 : else
749 : {
750 : papszSearchPath = CSLAddString( papszSearchPath,
751 : "/usr/local/lib/gdalplugins" );
752 : }
753 : #endif
754 :
755 : #ifdef MACOSX_FRAMEWORK
756 : papszSearchPath = CSLAddString( papszSearchPath,
757 : "/Library/Application Support/GDAL/PlugIns" );
758 : #endif
759 :
760 : }
761 :
762 : /* -------------------------------------------------------------------- */
763 : /* Scan each directory looking for files starting with gdal_ */
764 : /* -------------------------------------------------------------------- */
765 128 : for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
766 : {
767 64 : char **papszFiles = CPLReadDir( papszSearchPath[iDir] );
768 :
769 64 : for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
770 : {
771 : char *pszFuncName;
772 : const char *pszFilename;
773 0 : const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
774 : void *pRegister;
775 :
776 0 : if( !EQUALN(papszFiles[iFile],"ogr_",4) )
777 0 : continue;
778 :
779 0 : if( !EQUAL(pszExtension,"dll")
780 : && !EQUAL(pszExtension,"so")
781 : && !EQUAL(pszExtension,"dylib") )
782 0 : continue;
783 :
784 0 : pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
785 : sprintf( pszFuncName, "RegisterOGR%s",
786 0 : CPLGetBasename(papszFiles[iFile]) + 4 );
787 :
788 : pszFilename =
789 0 : CPLFormFilename( papszSearchPath[iDir],
790 0 : papszFiles[iFile], NULL );
791 :
792 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
793 0 : if( pRegister == NULL )
794 : {
795 0 : strcpy( pszFuncName, "GDALRegisterMe" );
796 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
797 : }
798 :
799 0 : if( pRegister != NULL )
800 : {
801 : CPLDebug( "OGR", "Auto register %s using %s.",
802 0 : pszFilename, pszFuncName );
803 :
804 0 : ((void (*)()) pRegister)();
805 : }
806 :
807 0 : CPLFree( pszFuncName );
808 : }
809 :
810 64 : CSLDestroy( papszFiles );
811 : }
812 :
813 64 : CSLDestroy( papszSearchPath );
814 64 : }
815 :
|