Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: KML Translator 4 : * Purpose: Implements OGRLIBKMLDriver 5 : * Author: Brian Case, rush at winkey dot org 6 : * 7 : ****************************************************************************** 8 : * Copyright (c) 2010, Brian Case 9 : * 10 : * SPDX-License-Identifier: MIT 11 : *****************************************************************************/ 12 : 13 : #include "libkml_headers.h" 14 : 15 : #include "ogr_libkml.h" 16 : #include "ogrlibkmldrivercore.h" 17 : #include "cpl_conv.h" 18 : #include "cpl_error.h" 19 : #include "cpl_multiproc.h" 20 : 21 : using kmldom::KmlFactory; 22 : 23 : static CPLMutex *hMutex = nullptr; 24 : static KmlFactory *m_poKmlFactory = nullptr; 25 : 26 : /****************************************************************************** 27 : OGRLIBKMLDriverUnload() 28 : ******************************************************************************/ 29 : 30 19 : static void OGRLIBKMLDriverUnload(GDALDriver * /* poDriver */) 31 : { 32 19 : if (hMutex != nullptr) 33 11 : CPLDestroyMutex(hMutex); 34 19 : hMutex = nullptr; 35 19 : m_poKmlFactory = nullptr; 36 19 : } 37 : 38 : /****************************************************************************** 39 : Open() 40 : ******************************************************************************/ 41 : 42 288 : static GDALDataset *OGRLIBKMLDriverOpen(GDALOpenInfo *poOpenInfo) 43 : { 44 288 : if (OGRLIBKMLDriverIdentify(poOpenInfo) == FALSE) 45 0 : return nullptr; 46 : 47 : { 48 576 : CPLMutexHolderD(&hMutex); 49 288 : if (m_poKmlFactory == nullptr) 50 12 : m_poKmlFactory = KmlFactory::GetFactory(); 51 : } 52 : 53 288 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource(m_poKmlFactory); 54 : 55 288 : if (!poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update)) 56 : { 57 162 : delete poDS; 58 : 59 162 : poDS = nullptr; 60 : } 61 : 62 288 : return poDS; 63 : } 64 : 65 : /************************************************************************/ 66 : /* Create() */ 67 : /************************************************************************/ 68 : 69 103 : static GDALDataset *OGRLIBKMLDriverCreate(const char *pszName, int /* nBands */, 70 : int /* nXSize */, int /* nYSize */, 71 : GDALDataType /* eDT */, 72 : char **papszOptions) 73 : { 74 103 : CPLAssert(nullptr != pszName); 75 103 : CPLDebug("LIBKML", "Attempt to create: %s", pszName); 76 : 77 : { 78 206 : CPLMutexHolderD(&hMutex); 79 103 : if (m_poKmlFactory == nullptr) 80 1 : m_poKmlFactory = KmlFactory::GetFactory(); 81 : } 82 : 83 103 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource(m_poKmlFactory); 84 : 85 103 : if (!poDS->Create(pszName, papszOptions)) 86 : { 87 1 : delete poDS; 88 : 89 1 : poDS = nullptr; 90 : } 91 : 92 103 : return poDS; 93 : } 94 : 95 : /****************************************************************************** 96 : DeleteDataSource() 97 : 98 : Note: This method recursively deletes an entire dir if the datasource is a dir 99 : and all the files are kml or kmz. 100 : 101 : ******************************************************************************/ 102 : 103 67 : static CPLErr OGRLIBKMLDriverDelete(const char *pszName) 104 : { 105 : /***** dir *****/ 106 : VSIStatBufL sStatBuf; 107 67 : if (!VSIStatL(pszName, &sStatBuf) && VSI_ISDIR(sStatBuf.st_mode)) 108 : { 109 32 : char **papszDirList = VSIReadDir(pszName); 110 32 : for (int iFile = 0; 111 32 : papszDirList != nullptr && papszDirList[iFile] != nullptr; iFile++) 112 : { 113 32 : if (CE_Failure == OGRLIBKMLDriverDelete(papszDirList[iFile])) 114 : { 115 32 : CSLDestroy(papszDirList); 116 32 : return CE_Failure; 117 : } 118 : } 119 0 : CSLDestroy(papszDirList); 120 : 121 0 : if (VSIRmdir(pszName) < 0) 122 : { 123 0 : return CE_Failure; 124 : } 125 : } 126 : 127 : /***** kml *****/ 128 35 : else if (EQUAL(CPLGetExtension(pszName), "kml")) 129 : { 130 35 : if (VSIUnlink(pszName) < 0) 131 32 : return CE_Failure; 132 : } 133 : 134 : /***** kmz *****/ 135 0 : else if (EQUAL(CPLGetExtension(pszName), "kmz")) 136 : { 137 0 : if (VSIUnlink(pszName) < 0) 138 0 : return CE_Failure; 139 : } 140 : 141 : /***** do not delete other types of files *****/ 142 : else 143 : { 144 0 : return CE_Failure; 145 : } 146 : 147 : // TODO(schwehr): Isn't this redundant to the else case? 148 3 : return CE_None; 149 : } 150 : 151 : /****************************************************************************** 152 : RegisterOGRLIBKML() 153 : ******************************************************************************/ 154 : 155 24 : void RegisterOGRLIBKML() 156 : { 157 24 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 158 0 : return; 159 : 160 24 : GDALDriver *poDriver = new GDALDriver(); 161 24 : OGRLIBKMLDriverSetCommonMetadata(poDriver); 162 : 163 24 : poDriver->pfnOpen = OGRLIBKMLDriverOpen; 164 24 : poDriver->pfnCreate = OGRLIBKMLDriverCreate; 165 24 : poDriver->pfnDelete = OGRLIBKMLDriverDelete; 166 24 : poDriver->pfnUnloadDriver = OGRLIBKMLDriverUnload; 167 : 168 24 : GetGDALDriverManager()->RegisterDriver(poDriver); 169 : }