1 : /******************************************************************************
2 : * $Id: FGdbDriver.cpp 23478 2011-12-05 23:15:46Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements FileGDB OGR driver.
6 : * Author: Ragi Yaser Burhum, ragi@burhum.com
7 : * Paul Ramsey, pramsey at cleverelephant.ca
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2010, Ragi Yaser Burhum
11 : * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogr_fgdb.h"
33 : #include "cpl_conv.h"
34 : #include "FGdbUtils.h"
35 :
36 : CPL_CVSID("$Id: FGdbDriver.cpp 23478 2011-12-05 23:15:46Z rouault $");
37 :
38 : extern "C" void RegisterOGRFileGDB();
39 :
40 : /************************************************************************/
41 : /* FGdbDriver() */
42 : /************************************************************************/
43 226 : FGdbDriver::FGdbDriver():
44 226 : OGRSFDriver()
45 : {
46 226 : }
47 :
48 : /************************************************************************/
49 : /* ~FGdbDriver() */
50 : /************************************************************************/
51 214 : FGdbDriver::~FGdbDriver()
52 :
53 : {
54 214 : }
55 :
56 :
57 : /************************************************************************/
58 : /* GetName() */
59 : /************************************************************************/
60 :
61 13967 : const char *FGdbDriver::GetName()
62 :
63 : {
64 13967 : return "FileGDB";
65 : }
66 :
67 : /************************************************************************/
68 : /* Open() */
69 : /************************************************************************/
70 :
71 206 : OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate )
72 :
73 : {
74 : // First check if we have to do any work.
75 206 : int nLen = strlen(pszFilename);
76 206 : if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) ||
77 : (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) )
78 191 : return NULL;
79 :
80 : long hr;
81 :
82 : /* Check that the filename is really a directory, to avoid confusion with */
83 : /* Garmin MapSource - gdb format which can be a problem when the FileGDB */
84 : /* driver is loaded as a plugin, and loaded before the GPSBabel driver */
85 : /* (http://trac.osgeo.org/osgeo4w/ticket/245) */
86 : VSIStatBuf stat;
87 15 : if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) )
88 : {
89 0 : return NULL;
90 : }
91 :
92 15 : Geodatabase* pGeoDatabase = new Geodatabase;
93 :
94 30 : hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase);
95 :
96 30 : if (FAILED(hr) || pGeoDatabase == NULL)
97 : {
98 0 : delete pGeoDatabase;
99 :
100 0 : GDBErr(hr, "Failed to open Geodatabase");
101 0 : return NULL;
102 : }
103 :
104 : FGdbDataSource* pDS;
105 :
106 15 : pDS = new FGdbDataSource();
107 :
108 15 : if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) )
109 : {
110 0 : delete pDS;
111 0 : return NULL;
112 : }
113 : else
114 15 : return pDS;
115 : }
116 :
117 : /***********************************************************************/
118 : /* CreateDataSource() */
119 : /***********************************************************************/
120 :
121 8 : OGRDataSource* FGdbDriver::CreateDataSource( const char * conn,
122 : char **papszOptions)
123 : {
124 : long hr;
125 : Geodatabase *pGeodatabase;
126 8 : std::wstring wconn = StringToWString(conn);
127 8 : int bUpdate = TRUE; // If we're creating, we must be writing.
128 : VSIStatBuf stat;
129 :
130 : /* We don't support options yet, so warn if they send us some */
131 : if ( papszOptions )
132 : {
133 : /* TODO: warning, ignoring options */
134 : }
135 :
136 : /* Only accept names of form "filename.gdb" and */
137 : /* also .gdb.zip to be able to return FGDB with MapServer OGR output (#4199) */
138 16 : const char* pszExt = CPLGetExtension(conn);
139 8 : if ( !(EQUAL(pszExt,"gdb") || EQUAL(pszExt, "zip")) )
140 : {
141 : CPLError( CE_Failure, CPLE_AppDefined,
142 0 : "FGDB data source name must use 'gdb' extension.\n" );
143 0 : return NULL;
144 : }
145 :
146 : /* Don't try to create on top of something already there */
147 8 : if( CPLStat( conn, &stat ) == 0 )
148 : {
149 : CPLError( CE_Failure, CPLE_AppDefined,
150 0 : "%s already exists.\n", conn );
151 0 : return NULL;
152 : }
153 :
154 : /* Try to create the geodatabase */
155 8 : pGeodatabase = new Geodatabase; // Create on heap so we can store it in the Datasource
156 16 : hr = CreateGeodatabase(wconn, *pGeodatabase);
157 :
158 : /* Handle creation errors */
159 8 : if ( S_OK != hr )
160 : {
161 0 : const char *errstr = "Error creating geodatabase (%s).\n";
162 0 : if ( hr == -2147220653 )
163 0 : errstr = "File already exists (%s).\n";
164 0 : delete pGeodatabase;
165 0 : CPLError( CE_Failure, CPLE_AppDefined, errstr, conn );
166 0 : return NULL;
167 : }
168 :
169 : /* Ready to embed the Geodatabase in an OGR Datasource */
170 8 : FGdbDataSource* pDS = new FGdbDataSource();
171 16 : if ( ! pDS->Open(pGeodatabase, conn, bUpdate) )
172 : {
173 0 : delete pDS;
174 0 : return NULL;
175 : }
176 : else
177 8 : return pDS;
178 : }
179 :
180 : /***********************************************************************/
181 : /* OpenGeodatabase() */
182 : /***********************************************************************/
183 :
184 0 : void FGdbDriver::OpenGeodatabase(std::string conn, Geodatabase** ppGeodatabase)
185 : {
186 0 : *ppGeodatabase = NULL;
187 :
188 0 : std::wstring wconn = StringToWString(conn);
189 :
190 : long hr;
191 :
192 0 : Geodatabase* pGeoDatabase = new Geodatabase;
193 :
194 0 : if (S_OK != (hr = ::OpenGeodatabase(wconn, *pGeoDatabase)))
195 : {
196 0 : delete pGeoDatabase;
197 :
198 : return;
199 : }
200 :
201 0 : *ppGeodatabase = pGeoDatabase;
202 : }
203 :
204 : /***********************************************************************/
205 : /* TestCapability() */
206 : /***********************************************************************/
207 :
208 1 : int FGdbDriver::TestCapability( const char * pszCap )
209 : {
210 1 : if (EQUAL(pszCap, ODrCCreateDataSource) )
211 1 : return TRUE;
212 :
213 0 : else if (EQUAL(pszCap, ODrCDeleteDataSource) )
214 0 : return TRUE;
215 :
216 0 : return FALSE;
217 : }
218 : /************************************************************************/
219 : /* DeleteDataSource() */
220 : /************************************************************************/
221 :
222 1 : OGRErr FGdbDriver::DeleteDataSource( const char *pszDataSource )
223 : {
224 :
225 1 : std::wstring wstr = StringToWString(pszDataSource);
226 :
227 : long hr;
228 :
229 2 : if (S_OK != (hr = ::DeleteGeodatabase(wstr)))
230 : {
231 0 : GDBErr(hr, "Failed to delete Geodatabase");
232 0 : return OGRERR_FAILURE;
233 : }
234 :
235 1 : return OGRERR_NONE;
236 : }
237 :
238 : /***********************************************************************/
239 : /* RegisterOGRFileGDB() */
240 : /***********************************************************************/
241 :
242 226 : void RegisterOGRFileGDB()
243 :
244 : {
245 226 : if (! GDAL_CHECK_VERSION("OGR FGDB"))
246 0 : return;
247 226 : OGRSFDriverRegistrar::GetRegistrar()->RegisterDriver( new FGdbDriver );
248 2139 : }
249 :
|