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 : * Permission is hereby granted, free of charge, to any person obtaining a 11 : * copy of this software and associated documentation files (the "Software"), 12 : * to deal in the Software without restriction, including without limitation 13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 14 : * and/or sell copies of the Software, and to permit persons to whom the 15 : * Software is furnished to do so, subject to the following conditions: 16 : * 17 : * The above copyright notice and this permission notice shall be included 18 : * in all copies or substantial portions of the Software. 19 : * 20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 : * DEALINGS IN THE SOFTWARE. 27 : *****************************************************************************/ 28 : 29 : #include "libkml_headers.h" 30 : 31 : #include "ogr_libkml.h" 32 : #include "ogrlibkmldrivercore.h" 33 : #include "cpl_conv.h" 34 : #include "cpl_error.h" 35 : #include "cpl_multiproc.h" 36 : 37 : using kmldom::KmlFactory; 38 : 39 : static CPLMutex *hMutex = nullptr; 40 : static KmlFactory *m_poKmlFactory = nullptr; 41 : 42 : /****************************************************************************** 43 : OGRLIBKMLDriverUnload() 44 : ******************************************************************************/ 45 : 46 13 : static void OGRLIBKMLDriverUnload(GDALDriver * /* poDriver */) 47 : { 48 13 : if (hMutex != nullptr) 49 10 : CPLDestroyMutex(hMutex); 50 13 : hMutex = nullptr; 51 13 : m_poKmlFactory = nullptr; 52 13 : } 53 : 54 : /****************************************************************************** 55 : Open() 56 : ******************************************************************************/ 57 : 58 234 : static GDALDataset *OGRLIBKMLDriverOpen(GDALOpenInfo *poOpenInfo) 59 : { 60 234 : if (OGRLIBKMLDriverIdentify(poOpenInfo) == FALSE) 61 0 : return nullptr; 62 : 63 : { 64 468 : CPLMutexHolderD(&hMutex); 65 234 : if (m_poKmlFactory == nullptr) 66 11 : m_poKmlFactory = KmlFactory::GetFactory(); 67 : } 68 : 69 234 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource(m_poKmlFactory); 70 : 71 234 : if (!poDS->Open(poOpenInfo->pszFilename, poOpenInfo->eAccess == GA_Update)) 72 : { 73 156 : delete poDS; 74 : 75 156 : poDS = nullptr; 76 : } 77 : 78 234 : return poDS; 79 : } 80 : 81 : /************************************************************************/ 82 : /* Create() */ 83 : /************************************************************************/ 84 : 85 67 : static GDALDataset *OGRLIBKMLDriverCreate(const char *pszName, int /* nBands */, 86 : int /* nXSize */, int /* nYSize */, 87 : GDALDataType /* eDT */, 88 : char **papszOptions) 89 : { 90 67 : CPLAssert(nullptr != pszName); 91 67 : CPLDebug("LIBKML", "Attempt to create: %s", pszName); 92 : 93 : { 94 134 : CPLMutexHolderD(&hMutex); 95 67 : if (m_poKmlFactory == nullptr) 96 1 : m_poKmlFactory = KmlFactory::GetFactory(); 97 : } 98 : 99 67 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource(m_poKmlFactory); 100 : 101 67 : if (!poDS->Create(pszName, papszOptions)) 102 : { 103 1 : delete poDS; 104 : 105 1 : poDS = nullptr; 106 : } 107 : 108 67 : return poDS; 109 : } 110 : 111 : /****************************************************************************** 112 : DeleteDataSource() 113 : 114 : Note: This method recursively deletes an entire dir if the datasource is a dir 115 : and all the files are kml or kmz. 116 : 117 : ******************************************************************************/ 118 : 119 67 : static CPLErr OGRLIBKMLDriverDelete(const char *pszName) 120 : { 121 : /***** dir *****/ 122 : VSIStatBufL sStatBuf; 123 67 : if (!VSIStatL(pszName, &sStatBuf) && VSI_ISDIR(sStatBuf.st_mode)) 124 : { 125 32 : char **papszDirList = VSIReadDir(pszName); 126 32 : for (int iFile = 0; 127 32 : papszDirList != nullptr && papszDirList[iFile] != nullptr; iFile++) 128 : { 129 32 : if (CE_Failure == OGRLIBKMLDriverDelete(papszDirList[iFile])) 130 : { 131 32 : CSLDestroy(papszDirList); 132 32 : return CE_Failure; 133 : } 134 : } 135 0 : CSLDestroy(papszDirList); 136 : 137 0 : if (VSIRmdir(pszName) < 0) 138 : { 139 0 : return CE_Failure; 140 : } 141 : } 142 : 143 : /***** kml *****/ 144 35 : else if (EQUAL(CPLGetExtension(pszName), "kml")) 145 : { 146 35 : if (VSIUnlink(pszName) < 0) 147 32 : return CE_Failure; 148 : } 149 : 150 : /***** kmz *****/ 151 0 : else if (EQUAL(CPLGetExtension(pszName), "kmz")) 152 : { 153 0 : if (VSIUnlink(pszName) < 0) 154 0 : return CE_Failure; 155 : } 156 : 157 : /***** do not delete other types of files *****/ 158 : else 159 : { 160 0 : return CE_Failure; 161 : } 162 : 163 : // TODO(schwehr): Isn't this redundant to the else case? 164 3 : return CE_None; 165 : } 166 : 167 : /****************************************************************************** 168 : RegisterOGRLIBKML() 169 : ******************************************************************************/ 170 : 171 17 : void RegisterOGRLIBKML() 172 : { 173 17 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr) 174 0 : return; 175 : 176 17 : GDALDriver *poDriver = new GDALDriver(); 177 17 : OGRLIBKMLDriverSetCommonMetadata(poDriver); 178 : 179 17 : poDriver->pfnOpen = OGRLIBKMLDriverOpen; 180 17 : poDriver->pfnCreate = OGRLIBKMLDriverCreate; 181 17 : poDriver->pfnDelete = OGRLIBKMLDriverDelete; 182 17 : poDriver->pfnUnloadDriver = OGRLIBKMLDriverUnload; 183 : 184 17 : GetGDALDriverManager()->RegisterDriver(poDriver); 185 : }