Statistics
| Revision:

gvsig-sqlite / trunk / org.gvsig.spatialite / org.gvsig.spatialite.provider / src / main / java / org / gvsig / spatialite / dal / SpatiaLiteHelper.java @ 118

History | View | Annotate | Download (12.3 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2016 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.spatialite.dal;
23

    
24
import java.io.File;
25
import org.gvsig.spatialite.dal.operations.SpatiaLiteOperationsFactory;
26
import java.sql.Connection;
27
import java.sql.SQLException;
28
import java.sql.Statement;
29
import java.util.Map;
30
import org.apache.commons.dbcp.BasicDataSource;
31
import org.apache.commons.io.FilenameUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.cresques.cts.IProjection;
34
import org.gvsig.fmap.dal.SQLBuilder;
35
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
36
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
37
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
38
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
39
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
40
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
41
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
42
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
43
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
44
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
45
import org.gvsig.fmap.geom.Geometry;
46
import org.gvsig.fmap.geom.aggregate.MultiLine;
47
import org.gvsig.fmap.geom.aggregate.MultiPoint;
48
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
49
import org.gvsig.fmap.geom.exception.CreateGeometryException;
50
import org.gvsig.fmap.geom.primitive.Primitive;
51
import org.gvsig.fmap.geom.type.GeometryType;
52
import org.slf4j.Logger;
53
import org.slf4j.LoggerFactory;
54
import org.sqlite.SQLiteConfig;
55
import org.sqlite.SQLiteConfig.TransactionMode;
56

    
57
public class SpatiaLiteHelper extends JDBCHelperBase {
58

    
59
    static final Logger logger = LoggerFactory.getLogger(SpatiaLiteHelper.class);
60

    
61
    public static final String NAME = "SpatiaLite";
62
    public static final String SpatiaLiteJDBCDriver = "org.sqlite.JDBC";
63
    public static final String URL_FORMAT = "jdbc:sqlite:%s";
64
    
65
    public static String getConnectionURL(SpatiaLiteConnectionParameters params) {
66
        String fname = params.getFile().getAbsolutePath().replace("\\","/");
67
        if( StringUtils.isEmpty(FilenameUtils.getExtension(fname)) ) {
68
            fname = fname + ".sqlite";
69
            params.setFile(new File(fname));
70
        }
71
        String driverClassName = params.getJDBCDriverClassName();
72
        if( StringUtils.isNotBlank(driverClassName) && 
73
            !StringUtils.equals(driverClassName, SpatiaLiteJDBCDriver) ) {
74
            try {
75
                Class.forName(driverClassName);
76
            } catch(Throwable th) {
77
                logger.warn("Can't load SpatiaLite JDBC Driver '"+driverClassName+"'.",th);
78
            }            
79
        }
80
        String connectionURLFormat = params.getURLFormat(); 
81
        if( StringUtils.isBlank(connectionURLFormat) ) {
82
            connectionURLFormat = URL_FORMAT;
83
        }
84
        String connectionURL = String.format(connectionURLFormat, fname);
85
        logger.debug("connectionURL: {}", connectionURL);
86
        return connectionURL;
87
    }
88

    
89
    private static class ConnectionProvider {
90

    
91
        private static boolean needRegisterDriver = true;
92

    
93
        private BasicDataSource dataSource = null;
94

    
95
        private final SpatiaLiteConnectionParameters connectionParameters;
96

    
97
        public ConnectionProvider(SpatiaLiteConnectionParameters connectionParameters) {
98
            this.connectionParameters = connectionParameters;
99
        }
100

    
101
        public Connection getConnection() throws SQLException {
102
            if (this.dataSource == null) {
103
                this.dataSource = this.createDataSource();               
104
            }
105
            Connection conn = this.dataSource.getConnection();
106
            loadExtension(conn);
107
            return conn;
108
        }
109

    
110
        private BasicDataSource createDataSource() throws SQLException {
111
            if (!this.isRegistered()) {
112
                this.registerDriver();
113
            }
114
            SpatiaLiteConnectionParameters params = connectionParameters;
115

    
116
            BasicDataSource ds = new BasicDataSource();
117
            ds.setDriverClassName(params.getJDBCDriverClassName());
118
            if( !StringUtils.isEmpty(params.getUser()) ) {
119
                ds.setUsername(params.getUser());
120
            }
121
            if( !StringUtils.isEmpty(params.getPassword()) ) {
122
                ds.setPassword(params.getPassword());
123
            }
124
            ds.setUrl(params.getUrl());
125
            SQLiteConfig config = new SQLiteConfig();
126
            config.setSharedCache(true);
127
            config.enableLoadExtension(true);
128
            config.setTransactionMode(TransactionMode.IMMEDIATE);
129
            for (Map.Entry e : config.toProperties().entrySet()) {
130
                ds.addConnectionProperty((String)e.getKey(), (String)e.getValue());
131
            }
132
            ds.setMaxWait(60L * 1000);
133
            return ds;
134
        }
135

    
136
        private boolean isRegistered() {
137
            return needRegisterDriver;
138
        }
139

    
140
        public void registerDriver() throws SQLException {
141
            String className = this.connectionParameters.getJDBCDriverClassName();
142
            if (className == null) {
143
                return;
144
            }
145
            try {
146
                Class theClass = Class.forName(className);
147
                if (theClass == null) {
148
                    throw new JDBCDriverClassNotFoundException(NAME, className);
149
                }
150
            } catch (Exception e) {
151
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
152
            }
153
            needRegisterDriver = false;
154
        }
155
        
156
        public void loadExtension(Connection conn) {
157
                    Statement st = null;
158
            try {
159
                st = conn.createStatement();
160
                st.execute("SELECT load_extension('mod_spatialite')");
161
            } catch(Exception ex) {
162
                logger.warn("Can't load mod_spatialite extension module for SQLite (" +
163
                        " driver class "+StringUtils.defaultString(connectionParameters.getJDBCDriverClassName()) +
164
                        " url format "+StringUtils.defaultString(connectionParameters.getURLFormat()) +
165
                        " file "+connectionParameters.getFile()==null?"null":connectionParameters.getFile().getAbsolutePath() +
166
                        ").", ex);
167
            }
168
            finally {
169
                    JDBCUtils.closeQuietly(st);
170
            }
171
            }
172
    }
173

    
174
    private ConnectionProvider connectionProvider = null;
175
   
176
    public SpatiaLiteHelper(JDBCConnectionParameters connectionParameters) {
177
        super(connectionParameters);
178
    }
179

    
180
    @Override
181
    public synchronized Connection  getConnection() throws AccessResourceException {
182
        try {
183
            if (this.connectionProvider == null) {
184
                this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
185
            }
186
            Connection connection = this.connectionProvider.getConnection();
187
            logger.debug("getConnection: connection = "+connection.hashCode());
188
            return connection;
189
        } catch (SQLException ex) {
190
            throw new AccessResourceException(SpatiaLiteLibrary.NAME, ex);
191
        }
192
    }
193
    
194
    @Override
195
    public SpatiaLiteConnectionParameters getConnectionParameters() {
196
        return (SpatiaLiteConnectionParameters) super.getConnectionParameters();
197
    }
198
    
199
    @Override
200
    public String getConnectionURL() {
201
        return getConnectionURL(this.getConnectionParameters());
202
    }
203

    
204
    @Override
205
    protected String getResourceType() {
206
        return SpatiaLiteLibrary.NAME;
207
    }
208

    
209
    @Override
210
    public String getProviderName() {
211
        return SpatiaLiteLibrary.NAME;
212
    }
213

    
214
    @Override
215
    public JDBCSQLBuilderBase createSQLBuilder() {
216
        return new SpatiaLiteSQLBuilder(this);
217
    }
218
    
219
    @Override
220
    public OperationsFactory getOperations() {
221
        if (this.operationsFactory == null) {
222
            this.operationsFactory = new SpatiaLiteOperationsFactory(this);
223
        }
224
        return operationsFactory;
225
    }
226

    
227
    @Override
228
    public SQLBuilder.GeometrySupportType getGeometrySupportType() {
229
        return SQLBuilder.GeometrySupportType.WKB;
230
    }
231

    
232
    @Override
233
    public boolean hasSpatialFunctions() {
234
        return true;
235
    }
236

    
237
    @Override
238
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
239
        return true;
240
    }
241

    
242
    @Override
243
    public String getQuoteForIdentifiers() {
244
        return "\"";
245
    }
246

    
247
    @Override
248
    public boolean allowAutomaticValues() {
249
        return true;
250
    }
251

    
252
    @Override
253
    public boolean supportOffsetInSelect() {
254
        return true;
255
    }
256

    
257
    @Override
258
    public String getQuoteForStrings() {
259
        return "'";
260
    }
261

    
262
    @Override
263
    public int getSRSCode(IProjection crs) {
264
        // TODO: ir a buscarlo a la BBDD a ver donde puede estar
265
        return super.getSRSCode(crs);
266
    }
267
    
268
    @Override
269
    public IProjection getProjectionFromSRSId(int srsid) {
270
        // TODO: ir a buscarlo a la BBDD a ver donde puede estar
271
        return super.getProjectionFromSRSId(srsid);
272
    }
273

    
274
    @Override
275
    public String getSourceId(JDBCStoreParameters parameters) {
276
        return parameters.getDBName() + "." + 
277
               parameters.getSchema()+ "." + 
278
               parameters.getTable();
279
    }
280

    
281
    @Override
282
    public JDBCNewStoreParameters createNewStoreParameters() {
283
        return new SpatiaLiteNewStoreParameters();
284
    }
285

    
286
    @Override
287
    public JDBCStoreParameters createOpenStoreParameters() {
288
        return new SpatiaLiteStoreParameters();
289
    }
290

    
291
    @Override
292
    public JDBCServerExplorerParameters createServerExplorerParameters() {
293
        return new SpatiaLiteExplorerParameters();
294
    }
295

    
296
    public Geometry forceGeometryType(GeometryType geomtype, Geometry geom) throws CreateGeometryException {
297
        if( geom == null ) {
298
            return null;
299
        }
300
        switch( geomtype.getType() ) {
301
        case Geometry.TYPES.MULTIPOLYGON:
302
            if( geom.getType()==Geometry.TYPES.POLYGON ) {
303
                MultiPolygon x = getGeometryManager().createMultiPolygon(geomtype.getSubType());
304
                x.addPrimitive((Primitive) geom);
305
                geom = x;
306
            }
307
            break;
308
        case Geometry.TYPES.MULTILINE:
309
            if( geom.getType()==Geometry.TYPES.LINE ) {
310
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
311
                x.addPrimitive((Primitive) geom);
312
                geom = x;
313
            }
314
            break;
315
        case Geometry.TYPES.MULTIPOINT:
316
            if( geom.getType()==Geometry.TYPES.POINT ) {
317
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
318
                x.addPrimitive((Primitive) geom);
319
                geom = x;
320
            }
321
            break;
322
        case Geometry.TYPES.POLYGON:
323
            if( geom.getType()==Geometry.TYPES.MULTIPOLYGON ) {
324
                MultiPolygon x = (MultiPolygon) geom;
325
                if( x.getPrimitivesNumber()==1 ) {
326
                    geom = x.getPrimitiveAt(0);
327
                }
328
            }
329
            break;
330
        case Geometry.TYPES.LINE:
331
            if( geom.getType()==Geometry.TYPES.MULTILINE ) {
332
                MultiLine x = (MultiLine) geom;
333
                if( x.getPrimitivesNumber()==1 ) {
334
                    geom = x.getPrimitiveAt(0);
335
                }
336
            }
337
            break;
338
        case Geometry.TYPES.POINT:
339
            if( geom.getType()==Geometry.TYPES.MULTIPOINT ) {
340
                MultiPoint x = (MultiPoint) geom;
341
                if( x.getPrimitivesNumber()==1 ) {
342
                    geom = x.getPrimitiveAt(0);
343
                }
344
            }
345
        }
346
        return geom;
347
    }
348
    
349
}