1 : /******************************************************************************
2 : * $Id: ogrsfdriverregistrar.cpp 19576 2010-04-29 19:31:49Z 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 19576 2010-04-29 19:31:49Z 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 80 : OGRSFDriverRegistrar::OGRSFDriverRegistrar()
55 :
56 : {
57 80 : CPLAssert( poRegistrar == NULL );
58 80 : nDrivers = 0;
59 80 : papoDrivers = NULL;
60 :
61 80 : nOpenDSCount = 0;
62 80 : papszOpenDSRawName = NULL;
63 80 : papoOpenDS = NULL;
64 80 : papoOpenDSDriver = NULL;
65 80 : 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 80 : if( CPLGetConfigOption( "GDAL_DATA", NULL ) != NULL )
80 : {
81 80 : 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 80 : }
94 :
95 : /************************************************************************/
96 : /* ~OGRSFDriverRegistrar() */
97 : /************************************************************************/
98 :
99 72 : OGRSFDriverRegistrar::~OGRSFDriverRegistrar()
100 :
101 : {
102 3024 : for( int i = 0; i < nDrivers; i++ )
103 : {
104 2952 : delete papoDrivers[i];
105 : }
106 :
107 72 : CPLFree( papoDrivers );
108 72 : papoDrivers = NULL;
109 :
110 72 : poRegistrar = NULL;
111 72 : }
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 339 : 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 339 : CPLMutexHolderD( &hDRMutex );
141 :
142 339 : if( poRegistrar != NULL )
143 72 : delete poRegistrar;
144 339 : OSRCleanup();
145 : }
146 :
147 339 : CPLFinderClean();
148 339 : VSICleanupFileManager();
149 339 : CPLFreeConfig();
150 339 : CPLCleanupTLS();
151 339 : }
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 4971 : OGRSFDriverRegistrar *OGRSFDriverRegistrar::GetRegistrar()
169 :
170 : {
171 4971 : if( poRegistrar == NULL )
172 : {
173 80 : CPLMutexHolderD( &hDRMutex );
174 :
175 80 : if( poRegistrar == NULL )
176 80 : poRegistrar = new OGRSFDriverRegistrar();
177 : }
178 :
179 4971 : CPLAssert( NULL != poRegistrar );
180 4971 : return poRegistrar;
181 : }
182 :
183 : /************************************************************************/
184 : /* Open() */
185 : /************************************************************************/
186 :
187 : OGRDataSource *OGRSFDriverRegistrar::Open( const char * pszName,
188 : int bUpdate,
189 537 : OGRSFDriver ** ppoDriver )
190 :
191 : {
192 : OGRDataSource *poDS;
193 :
194 537 : if( ppoDriver != NULL )
195 26 : *ppoDriver = NULL;
196 :
197 537 : GetRegistrar();
198 :
199 537 : CPLErrorReset();
200 :
201 537 : CPLAcquireMutex( hDRMutex, 0.1 );
202 :
203 6330 : for( int iDriver = 0; iDriver < poRegistrar->nDrivers; iDriver++ )
204 : {
205 6325 : OGRSFDriver *poDriver = poRegistrar->papoDrivers[iDriver];
206 :
207 6325 : CPLReleaseMutex( hDRMutex );
208 :
209 6325 : poDS = poDriver->Open( pszName, bUpdate );
210 6325 : if( poDS != NULL )
211 : {
212 528 : if( ppoDriver != NULL )
213 26 : *ppoDriver = poDriver;
214 :
215 528 : poDS->Reference();
216 528 : if( poDS->GetDriver() == NULL )
217 528 : poDS->m_poDriver = poDriver;
218 :
219 : CPLDebug( "OGR", "OGROpen(%s/%p) succeeded as %s.",
220 528 : pszName, poDS, poDS->GetDriver()->GetName() );
221 :
222 528 : return poDS;
223 : }
224 :
225 5797 : if( CPLGetLastErrorType() == CE_Failure )
226 4 : return NULL;
227 :
228 5793 : CPLAcquireMutex( hDRMutex, 0.1 );
229 : }
230 :
231 5 : CPLReleaseMutex( hDRMutex );
232 :
233 5 : CPLDebug( "OGR", "OGROpen(%s) failed.", pszName );
234 :
235 5 : return NULL;
236 : }
237 :
238 : /************************************************************************/
239 : /* OGROpen() */
240 : /************************************************************************/
241 :
242 : OGRDataSourceH OGROpen( const char *pszName, int bUpdate,
243 443 : OGRSFDriverH *pahDriverList )
244 :
245 : {
246 443 : VALIDATE_POINTER1( pszName, "OGROpen", NULL );
247 :
248 443 : if (poRegistrar)
249 : return (OGRDataSourceH)
250 : poRegistrar->Open( pszName, bUpdate,
251 443 : (OGRSFDriver **) pahDriverList );
252 :
253 0 : return NULL;
254 : }
255 :
256 : /************************************************************************/
257 : /* OpenShared() */
258 : /************************************************************************/
259 :
260 : OGRDataSource *
261 : OGRSFDriverRegistrar::OpenShared( const char * pszName, int bUpdate,
262 24 : OGRSFDriver ** ppoDriver )
263 :
264 : {
265 : OGRDataSource *poDS;
266 :
267 24 : if( ppoDriver != NULL )
268 0 : *ppoDriver = NULL;
269 :
270 24 : 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 24 : CPLMutexHolderD( &hDRMutex );
284 24 : GIntBig nThisPID = CPLGetPID();
285 :
286 35 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
287 : {
288 25 : poDS = papoOpenDS[iDS];
289 :
290 25 : if( strcmp( pszName, papszOpenDSRawName[iDS]) == 0
291 : && 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 15 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
306 : {
307 5 : poDS = papoOpenDS[iDS];
308 :
309 5 : if( strcmp( pszName, poDS->GetName()) == 0
310 : && nThisPID == panOpenDSPID[iDS] )
311 : {
312 0 : poDS->Reference();
313 :
314 0 : if( ppoDriver != NULL )
315 0 : *ppoDriver = papoOpenDSDriver[iDS];
316 14 : return poDS;
317 : }
318 0 : }
319 : }
320 :
321 : /* -------------------------------------------------------------------- */
322 : /* We don't have the datasource. Open it normally. */
323 : /* -------------------------------------------------------------------- */
324 10 : OGRSFDriver *poTempDriver = NULL;
325 :
326 10 : poDS = Open( pszName, bUpdate, &poTempDriver );
327 :
328 10 : 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 10 : CPLMutexHolderD( &hDRMutex );
337 :
338 : papszOpenDSRawName = (char **)
339 10 : CPLRealloc( papszOpenDSRawName, sizeof(char*) * (nOpenDSCount+1) );
340 :
341 : papoOpenDS = (OGRDataSource **)
342 10 : CPLRealloc( papoOpenDS, sizeof(char*) * (nOpenDSCount+1) );
343 :
344 : papoOpenDSDriver = (OGRSFDriver **)
345 10 : CPLRealloc( papoOpenDSDriver, sizeof(char*) * (nOpenDSCount+1) );
346 :
347 : panOpenDSPID = (GIntBig *)
348 10 : CPLRealloc( panOpenDSPID, sizeof(GIntBig) * (nOpenDSCount+1) );
349 :
350 10 : papszOpenDSRawName[nOpenDSCount] = CPLStrdup( pszName );
351 10 : papoOpenDS[nOpenDSCount] = poDS;
352 10 : papoOpenDSDriver[nOpenDSCount] = poTempDriver;
353 10 : panOpenDSPID[nOpenDSCount] = CPLGetPID();
354 :
355 10 : nOpenDSCount++;
356 : }
357 :
358 10 : if( ppoDriver != NULL )
359 0 : *ppoDriver = poTempDriver;
360 :
361 10 : return poDS;
362 : }
363 :
364 : /************************************************************************/
365 : /* OGROpenShared() */
366 : /************************************************************************/
367 :
368 : OGRDataSourceH OGROpenShared( const char *pszName, int bUpdate,
369 17 : OGRSFDriverH *pahDriverList )
370 :
371 : {
372 17 : VALIDATE_POINTER1( pszName, "OGROpenShared", NULL );
373 :
374 17 : OGRSFDriverRegistrar::GetRegistrar();
375 : return (OGRDataSourceH)
376 : poRegistrar->OpenShared( pszName, bUpdate,
377 17 : (OGRSFDriver **) pahDriverList );
378 : }
379 :
380 : /************************************************************************/
381 : /* ReleaseDataSource() */
382 : /************************************************************************/
383 :
384 620 : OGRErr OGRSFDriverRegistrar::ReleaseDataSource( OGRDataSource * poDS )
385 :
386 : {
387 : {
388 620 : CPLMutexHolderD( &hDRMutex );
389 :
390 : int iDS;
391 :
392 643 : for( iDS = 0; iDS < nOpenDSCount; iDS++ )
393 : {
394 43 : if( poDS == papoOpenDS[iDS] )
395 20 : break;
396 : }
397 :
398 620 : if( iDS == nOpenDSCount )
399 : {
400 : CPLDebug( "OGR",
401 : "ReleaseDataSource(%s/%p) on unshared datasource!\n"
402 : "Deleting directly.",
403 600 : poDS->GetName(), poDS );
404 600 : delete poDS;
405 1210 : return OGRERR_FAILURE;
406 : }
407 :
408 20 : if( poDS->GetRefCount() > 0 )
409 20 : poDS->Dereference();
410 :
411 20 : 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 10 : 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 10 : poDS->GetName(), poDS );
436 :
437 10 : CPLFree( papszOpenDSRawName[iDS] );
438 : memmove( papszOpenDSRawName + iDS, papszOpenDSRawName + iDS + 1,
439 10 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
440 : memmove( papoOpenDS + iDS, papoOpenDS + iDS + 1,
441 10 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
442 : memmove( papoOpenDSDriver + iDS, papoOpenDSDriver + iDS + 1,
443 10 : sizeof(char *) * (nOpenDSCount - iDS - 1) );
444 : memmove( panOpenDSPID + iDS, panOpenDSPID + iDS + 1,
445 10 : sizeof(GIntBig) * (nOpenDSCount - iDS - 1) );
446 :
447 10 : nOpenDSCount--;
448 :
449 10 : 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 10 : delete poDS;
470 :
471 10 : return OGRERR_NONE;
472 : }
473 :
474 : /************************************************************************/
475 : /* OGRReleaseDataSource() */
476 : /************************************************************************/
477 :
478 609 : OGRErr OGRReleaseDataSource( OGRDataSourceH hDS )
479 :
480 : {
481 609 : VALIDATE_POINTER1( hDS, "OGRReleaseDataSource", OGRERR_INVALID_HANDLE );
482 :
483 609 : OGRSFDriverRegistrar::GetRegistrar();
484 609 : 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 3282 : void OGRSFDriverRegistrar::RegisterDriver( OGRSFDriver * poDriver )
529 :
530 : {
531 3282 : CPLMutexHolderD( &hDRMutex );
532 : int iDriver;
533 :
534 : /* -------------------------------------------------------------------- */
535 : /* It has no effect to register a driver more than once. */
536 : /* -------------------------------------------------------------------- */
537 68962 : for( iDriver = 0; iDriver < nDrivers; iDriver++ )
538 : {
539 65680 : if( poDriver == papoDrivers[iDriver] )
540 0 : return;
541 :
542 : /* Same name but different pointer. Likely a second call to OGRRegisterAll() */
543 : /* We delete the new driver */
544 65680 : 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 3282 : CSLTokenizeStringComplex(CPLGetConfigOption("OGR_SKIP", ""), ",", FALSE, FALSE);
556 3282 : char** iter = papszSkipDrivers;
557 6564 : 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 3282 : CSLDestroy(papszSkipDrivers);
568 :
569 : /* -------------------------------------------------------------------- */
570 : /* Add to the end of the driver list. */
571 : /* -------------------------------------------------------------------- */
572 : papoDrivers = (OGRSFDriver **)
573 3282 : CPLRealloc( papoDrivers, (nDrivers+1) * sizeof(void*) );
574 :
575 3282 : papoDrivers[nDrivers++] = poDriver;
576 : }
577 :
578 : /************************************************************************/
579 : /* OGRRegisterDriver() */
580 : /************************************************************************/
581 :
582 2 : void OGRRegisterDriver( OGRSFDriverH hDriver )
583 :
584 : {
585 2 : VALIDATE_POINTER0( hDriver, "OGRRegisterDriver" );
586 :
587 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver(
588 2 : (OGRSFDriver *) hDriver );
589 : }
590 :
591 : /************************************************************************/
592 : /* DeregisterDriver() */
593 : /************************************************************************/
594 :
595 2 : void OGRSFDriverRegistrar::DeregisterDriver( OGRSFDriver * poDriver )
596 :
597 : {
598 2 : CPLMutexHolderD( &hDRMutex );
599 : int i;
600 :
601 32 : for( i = 0; i < nDrivers; i++ )
602 : {
603 32 : if( poDriver == papoDrivers[i] )
604 2 : break;
605 : }
606 :
607 2 : if (i == nDrivers)
608 0 : return;
609 :
610 54 : while( i < nDrivers-1 )
611 : {
612 50 : papoDrivers[i] = papoDrivers[i+1];
613 50 : i++;
614 : }
615 2 : nDrivers--;
616 : }
617 :
618 : /************************************************************************/
619 : /* OGRDeregisterDriver() */
620 : /************************************************************************/
621 :
622 2 : void OGRDeregisterDriver( OGRSFDriverH hDriver )
623 :
624 : {
625 2 : VALIDATE_POINTER0( hDriver, "OGRDeregisterDriver" );
626 :
627 : OGRSFDriverRegistrar::GetRegistrar()->DeregisterDriver(
628 2 : (OGRSFDriver *) hDriver );
629 : }
630 :
631 : /************************************************************************/
632 : /* GetDriverCount() */
633 : /************************************************************************/
634 :
635 220 : int OGRSFDriverRegistrar::GetDriverCount()
636 :
637 : {
638 220 : return nDrivers;
639 : }
640 :
641 : /************************************************************************/
642 : /* OGRGetDriverCount() */
643 : /************************************************************************/
644 :
645 68 : int OGRGetDriverCount()
646 :
647 : {
648 68 : if (poRegistrar)
649 67 : return poRegistrar->GetDriverCount();
650 :
651 1 : return 0;
652 : }
653 :
654 : /************************************************************************/
655 : /* GetDriver() */
656 : /************************************************************************/
657 :
658 230 : OGRSFDriver *OGRSFDriverRegistrar::GetDriver( int iDriver )
659 :
660 : {
661 230 : CPLMutexHolderD( &hDRMutex );
662 :
663 230 : if( iDriver < 0 || iDriver >= nDrivers )
664 0 : return NULL;
665 : else
666 230 : return papoDrivers[iDriver];
667 : }
668 :
669 : /************************************************************************/
670 : /* OGRGetDriver() */
671 : /************************************************************************/
672 :
673 77 : OGRSFDriverH OGRGetDriver( int iDriver )
674 :
675 : {
676 77 : VALIDATE_POINTER1( poRegistrar, "OGRGetDriver", NULL );
677 :
678 77 : return (OGRSFDriverH) poRegistrar->GetDriver( iDriver );
679 : }
680 :
681 : /************************************************************************/
682 : /* GetDriverByName() */
683 : /************************************************************************/
684 :
685 254 : OGRSFDriver *OGRSFDriverRegistrar::GetDriverByName( const char * pszName )
686 :
687 : {
688 254 : CPLMutexHolderD( &hDRMutex );
689 :
690 2288 : for( int i = 0; i < nDrivers; i++ )
691 : {
692 2283 : if( papoDrivers[i] != NULL
693 : && EQUAL(papoDrivers[i]->GetName(),pszName) )
694 249 : return papoDrivers[i];
695 : }
696 :
697 5 : return NULL;
698 : }
699 :
700 : /************************************************************************/
701 : /* OGRGetDriverByName() */
702 : /************************************************************************/
703 :
704 253 : OGRSFDriverH OGRGetDriverByName( const char *pszName )
705 :
706 : {
707 253 : VALIDATE_POINTER1( pszName, "OGRGetDriverByName", NULL );
708 :
709 : return (OGRSFDriverH)
710 253 : OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName( pszName );
711 : }
712 :
713 : /************************************************************************/
714 : /* AutoLoadDrivers() */
715 : /************************************************************************/
716 :
717 : /**
718 : * \brief Auto-load GDAL drivers from shared libraries.
719 : *
720 : * This function will automatically load drivers from shared libraries. It
721 : * searches the "driver path" for .so (or .dll) files that start with the
722 : * prefix "ogr_X.so". It then tries to load them and then tries to call
723 : * a function within them called RegisterOGRX() where the 'X' is the same
724 : * as the remainder of the shared library basename, or failing that to
725 : * call GDALRegisterMe().
726 : *
727 : * There are a few rules for the driver path. If the GDAL_DRIVER_PATH
728 : * environment variable it set, it is taken to be a list of directories to
729 : * search separated by colons on unix, or semi-colons on Windows.
730 : *
731 : * If that is not set the following defaults are used:
732 : *
733 : * <ul>
734 : * <li> Linux/Unix: <prefix>/lib/gdalplugins is searched or
735 : * /usr/local/lib/gdalplugins if the install prefix is not known.
736 : * <li> MacOSX: <prefix>/PlugIns is searched, or /usr/local/lib/gdalplugins if
737 : * the install prefix is not known. Also, the framework directory
738 : * /Library/Application Support/GDAL/PlugIns is searched.
739 : * <li> Win32: <prefix>/lib/gdalplugins if the prefix is known (normally it
740 : * is not), otherwise the gdalplugins subdirectory of the directory containing
741 : * the currently running executable is used.
742 : * </ul>
743 : */
744 :
745 80 : void OGRSFDriverRegistrar::AutoLoadDrivers()
746 :
747 : {
748 80 : char **papszSearchPath = NULL;
749 : const char *pszGDAL_DRIVER_PATH =
750 80 : CPLGetConfigOption( "OGR_DRIVER_PATH", NULL );
751 :
752 80 : if( pszGDAL_DRIVER_PATH == NULL )
753 : pszGDAL_DRIVER_PATH =
754 80 : CPLGetConfigOption( "GDAL_DRIVER_PATH", NULL );
755 :
756 : /* -------------------------------------------------------------------- */
757 : /* Where should we look for stuff? */
758 : /* -------------------------------------------------------------------- */
759 80 : if( pszGDAL_DRIVER_PATH != NULL )
760 : {
761 : #ifdef WIN32
762 : papszSearchPath =
763 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ";", TRUE, FALSE );
764 : #else
765 : papszSearchPath =
766 80 : CSLTokenizeStringComplex( pszGDAL_DRIVER_PATH, ":", TRUE, FALSE );
767 : #endif
768 : }
769 : else
770 : {
771 : #ifdef GDAL_PREFIX
772 : papszSearchPath = CSLAddString( papszSearchPath,
773 : #ifdef MACOSX_FRAMEWORK
774 : GDAL_PREFIX "/PlugIns");
775 : #else
776 0 : GDAL_PREFIX "/lib/gdalplugins" );
777 : #endif
778 : #else
779 : char szExecPath[1024];
780 :
781 : if( CPLGetExecPath( szExecPath, sizeof(szExecPath) ) )
782 : {
783 : char szPluginDir[sizeof(szExecPath)+50];
784 : strcpy( szPluginDir, CPLGetDirname( szExecPath ) );
785 : strcat( szPluginDir, "\\gdalplugins\\" );
786 : papszSearchPath = CSLAddString( papszSearchPath, szPluginDir );
787 : }
788 : else
789 : {
790 : papszSearchPath = CSLAddString( papszSearchPath,
791 : "/usr/local/lib/gdalplugins" );
792 : }
793 : #endif
794 :
795 : #ifdef MACOSX_FRAMEWORK
796 : #define num2str(x) str(x)
797 : #define str(x) #x
798 : papszSearchPath = CSLAddString( papszSearchPath,
799 : "/Library/Application Support/GDAL/"
800 : num2str(GDAL_VERSION_MAJOR) "."
801 : num2str(GDAL_VERSION_MINOR) "/PlugIns" );
802 : #endif
803 :
804 : }
805 :
806 : /* -------------------------------------------------------------------- */
807 : /* Scan each directory looking for files starting with gdal_ */
808 : /* -------------------------------------------------------------------- */
809 160 : for( int iDir = 0; iDir < CSLCount(papszSearchPath); iDir++ )
810 : {
811 80 : char **papszFiles = CPLReadDir( papszSearchPath[iDir] );
812 :
813 5200 : for( int iFile = 0; iFile < CSLCount(papszFiles); iFile++ )
814 : {
815 : char *pszFuncName;
816 : const char *pszFilename;
817 5120 : const char *pszExtension = CPLGetExtension( papszFiles[iFile] );
818 : void *pRegister;
819 :
820 5120 : if( !EQUALN(papszFiles[iFile],"ogr_",4) )
821 5120 : continue;
822 :
823 0 : if( !EQUAL(pszExtension,"dll")
824 : && !EQUAL(pszExtension,"so")
825 : && !EQUAL(pszExtension,"dylib") )
826 0 : continue;
827 :
828 0 : pszFuncName = (char *) CPLCalloc(strlen(papszFiles[iFile])+20,1);
829 : sprintf( pszFuncName, "RegisterOGR%s",
830 0 : CPLGetBasename(papszFiles[iFile]) + 4 );
831 :
832 : pszFilename =
833 : CPLFormFilename( papszSearchPath[iDir],
834 0 : papszFiles[iFile], NULL );
835 :
836 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
837 0 : if( pRegister == NULL )
838 : {
839 0 : strcpy( pszFuncName, "GDALRegisterMe" );
840 0 : pRegister = CPLGetSymbol( pszFilename, pszFuncName );
841 : }
842 :
843 0 : if( pRegister != NULL )
844 : {
845 : CPLDebug( "OGR", "Auto register %s using %s.",
846 0 : pszFilename, pszFuncName );
847 :
848 0 : ((void (*)()) pRegister)();
849 : }
850 :
851 0 : CPLFree( pszFuncName );
852 : }
853 :
854 80 : CSLDestroy( papszFiles );
855 : }
856 :
857 80 : CSLDestroy( papszSearchPath );
858 80 : }
859 :
|