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 "ogr_libkml.h"
30 : #include "cpl_conv.h"
31 : #include "cpl_error.h"
32 : #include "cpl_atomic_ops.h"
33 :
34 : #include <kml/dom.h>
35 :
36 : using kmldom::KmlFactory;
37 :
38 : static volatile int nKmlFactoryRefCount = 0;
39 :
40 : /******************************************************************************
41 : OGRLIBKMLDriver()
42 : ******************************************************************************/
43 :
44 389 : OGRLIBKMLDriver::OGRLIBKMLDriver ( )
45 : {
46 389 : CPLAtomicInc(&nKmlFactoryRefCount);
47 389 : m_poKmlFactory = KmlFactory::GetFactory ( );
48 :
49 389 : }
50 :
51 : /******************************************************************************
52 : ~OGRLIBKMLDriver()
53 : ******************************************************************************/
54 :
55 369 : OGRLIBKMLDriver::~OGRLIBKMLDriver ( )
56 : {
57 369 : if (CPLAtomicDec(&nKmlFactoryRefCount) == 0)
58 363 : delete m_poKmlFactory;
59 369 : }
60 :
61 : /******************************************************************************
62 : GetName()
63 : ******************************************************************************/
64 :
65 23635 : const char *OGRLIBKMLDriver::GetName (
66 : )
67 : {
68 :
69 23635 : return "LIBKML";
70 : }
71 :
72 : /******************************************************************************
73 : Open()
74 : ******************************************************************************/
75 :
76 492 : OGRDataSource *OGRLIBKMLDriver::Open (
77 : const char *pszFilename,
78 : int bUpdate )
79 : {
80 492 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource ( m_poKmlFactory );
81 :
82 492 : if ( !poDS->Open ( pszFilename, bUpdate ) ) {
83 470 : delete poDS;
84 :
85 470 : poDS = NULL;
86 : }
87 :
88 492 : return poDS;
89 : }
90 :
91 : /******************************************************************************
92 : CreateDataSource()
93 : ******************************************************************************/
94 :
95 6 : OGRDataSource *OGRLIBKMLDriver::CreateDataSource (
96 : const char *pszName,
97 : char **papszOptions )
98 : {
99 6 : CPLAssert ( NULL != pszName );
100 6 : CPLDebug ( "LIBKML", "Attempt to create: %s", pszName );
101 :
102 6 : OGRLIBKMLDataSource *poDS = new OGRLIBKMLDataSource ( m_poKmlFactory );
103 :
104 6 : if ( !poDS->Create ( pszName, papszOptions ) ) {
105 0 : delete poDS;
106 :
107 0 : poDS = NULL;
108 : }
109 :
110 6 : return poDS;
111 : }
112 :
113 : /******************************************************************************
114 : DeleteDataSource()
115 :
116 : note: this method recursivly deletes an entire dir if the datasource is a dir
117 : and all the files are kml or kmz
118 :
119 : ******************************************************************************/
120 :
121 0 : OGRErr OGRLIBKMLDriver::DeleteDataSource (
122 : const char *pszName )
123 : {
124 :
125 : /***** dir *****/
126 :
127 0 : VSIStatBufL sStatBuf = { };
128 0 : if ( !VSIStatL ( pszName, &sStatBuf ) && VSI_ISDIR ( sStatBuf.st_mode ) ) {
129 :
130 0 : char **papszDirList = NULL;
131 :
132 0 : if ( !( papszDirList = VSIReadDir ( pszName ) ) ) {
133 0 : if ( VSIRmdir ( pszName ) < 0 )
134 0 : return OGRERR_FAILURE;
135 : }
136 :
137 0 : int nFiles = CSLCount ( papszDirList );
138 : int iFile;
139 :
140 0 : for ( iFile = 0; iFile < nFiles; iFile++ ) {
141 0 : if ( OGRERR_FAILURE ==
142 0 : this->DeleteDataSource ( papszDirList[iFile] ) ) {
143 0 : CSLDestroy ( papszDirList );
144 0 : return OGRERR_FAILURE;
145 : }
146 : }
147 :
148 0 : if ( VSIRmdir ( pszName ) < 0 ) {
149 0 : CSLDestroy ( papszDirList );
150 0 : return OGRERR_FAILURE;
151 : }
152 :
153 0 : CSLDestroy ( papszDirList );
154 : }
155 :
156 : /***** kml *****/
157 :
158 0 : else if ( EQUAL ( CPLGetExtension ( pszName ), "kml" ) ) {
159 0 : if ( VSIUnlink ( pszName ) < 0 )
160 0 : return OGRERR_FAILURE;
161 : }
162 :
163 : /***** kmz *****/
164 :
165 0 : else if ( EQUAL ( CPLGetExtension ( pszName ), "kmz" ) ) {
166 0 : if ( VSIUnlink ( pszName ) < 0 )
167 0 : return OGRERR_FAILURE;
168 : }
169 :
170 : /***** do not delete other types of files *****/
171 :
172 : else
173 0 : return OGRERR_FAILURE;
174 :
175 0 : return OGRERR_NONE;
176 : }
177 :
178 : /******************************************************************************
179 : TestCapability()
180 : ******************************************************************************/
181 :
182 0 : int OGRLIBKMLDriver::TestCapability (
183 : const char *pszCap )
184 : {
185 0 : if ( EQUAL ( pszCap, ODrCCreateDataSource ) )
186 0 : return TRUE;
187 :
188 0 : else if ( EQUAL ( pszCap, ODrCDeleteDataSource ) )
189 0 : return TRUE;
190 :
191 0 : return FALSE;
192 : }
193 :
194 : /******************************************************************************
195 : RegisterOGRLIBKML()
196 : ******************************************************************************/
197 :
198 389 : void RegisterOGRLIBKML (
199 : )
200 : {
201 : OGRSFDriverRegistrar::GetRegistrar ( )->
202 389 : RegisterDriver ( new OGRLIBKMLDriver );
203 :
204 389 : }
|