Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.h2 / src / main / java / org / gvsig / fmap / dal / store / h2 / H2SpatialHelper.java @ 44361

History | View | Annotate | Download (13.5 KB)

1 43377 jjdelcerro
/* 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.fmap.dal.store.h2;
23
24
import java.sql.Connection;
25
import java.sql.SQLException;
26
import java.text.MessageFormat;
27
import org.apache.commons.dbcp.BasicDataSource;
28
import org.apache.commons.io.FilenameUtils;
29
import org.apache.commons.lang3.StringUtils;
30 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.GeometrySupportType;
31 44160 jjdelcerro
import org.gvsig.fmap.dal.exception.InitializeException;
32 43377 jjdelcerro
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
33 44160 jjdelcerro
import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices;
34 43377 jjdelcerro
import org.gvsig.fmap.dal.store.h2.operations.H2SpatialOperationsFactory;
35
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
36
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
37
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
38
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
39
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
40 44160 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
41 43377 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
42
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
43
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
44 44160 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCServerExplorerBase;
45 43606 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverBase;
46 43892 jjdelcerro
import org.h2.tools.Server;
47 43377 jjdelcerro
import org.h2gis.ext.H2GISExtension;
48
import org.slf4j.Logger;
49
import org.slf4j.LoggerFactory;
50
51 44198 jjdelcerro
@SuppressWarnings("UseSpecificCatch")
52 43377 jjdelcerro
public class H2SpatialHelper extends JDBCHelperBase {
53
54 44198 jjdelcerro
    static final Logger LOGGER = LoggerFactory.getLogger(H2SpatialHelper.class);
55 43377 jjdelcerro
56 44198 jjdelcerro
    public static final String H2SPATIAL_JDBC_DRIVER = "org.h2.Driver";
57 43892 jjdelcerro
58 43377 jjdelcerro
    public static String getConnectionURL(H2SpatialConnectionParameters params) {
59
        String connectionURL;
60 43892 jjdelcerro
        String dbfilename = params.getFile().getAbsolutePath().replace("\\","/");
61
        if( dbfilename!=null && dbfilename.endsWith(".mv.db") ) {
62
            dbfilename = dbfilename.substring(0, dbfilename.length()-6);
63
        }
64 44361 jjdelcerro
        StringBuilder commonParameters = new StringBuilder();
65
        commonParameters.append(";MODE=PostgreSQL");
66
        commonParameters.append(";SCHEMA=PUBLIC");
67
        commonParameters.append(";ALLOW_LITERALS=ALL");
68
69
//        Integer LOCK_TIMEOUT = (Integer) params.getDynValue("LOCK_TIMEOUT");
70
//        if( LOCK_TIMEOUT!=null ) {
71
//            commonParameters.append(";LOCK_TIMEOUT=").append(LOCK_TIMEOUT);
72
//        }
73
//        Integer MULTI_THREADED = (Integer) params.getDynValue("MULTI_THREADED");
74
//        if( MULTI_THREADED!=null ) {
75
//            commonParameters.append(";MULTI_THREADED=").append(MULTI_THREADED);
76
//        }
77
//        Integer CHACHE_SIZE = (Integer) params.getDynValue("CHACHE_SIZE");
78
//        if( LOCK_TIMEOUT!=null ) {
79
//            commonParameters.append(";CHACHE_SIZE=").append(CHACHE_SIZE);
80
//        }
81
//        Integer LOG = (Integer) params.getDynValue("LOG");
82
//        if( LOCK_TIMEOUT!=null ) {
83
//            commonParameters.append(";LOG=").append(LOG);
84
//        }
85
//        Integer LOCK_MODE = (Integer) params.getDynValue("LOCK_MODE");
86
//        if( LOCK_TIMEOUT!=null ) {
87
//            commonParameters.append(";LOCK_MODE=").append(LOCK_MODE);
88
//        }
89
90 43377 jjdelcerro
        if( StringUtils.isEmpty(params.getHost()) ) {
91
            // Asumimos que es una conexion directa sobre el filesystem
92
            if( StringUtils.equalsIgnoreCase(FilenameUtils.getExtension(params.getFile().getName()),"zip") ) {
93
                connectionURL =  MessageFormat.format(
94 44361 jjdelcerro
                    "jdbc:h2:zip:{0}!/{1}"+commonParameters.toString(),
95 43892 jjdelcerro
                    dbfilename,
96 43377 jjdelcerro
                    params.getDBName()
97
                );
98
            } else {
99
                connectionURL =  MessageFormat.format(
100 44361 jjdelcerro
                    "jdbc:h2:file:{0}"+commonParameters.toString(),
101 43892 jjdelcerro
                    dbfilename
102 43377 jjdelcerro
                );
103
            }
104
        } else if( params.getPort() == null ) {
105
            connectionURL =  MessageFormat.format(
106 44361 jjdelcerro
                "jdbc:h2:tcp://{0}/{1}"+commonParameters.toString(),
107 43377 jjdelcerro
                params.getHost(),
108 43892 jjdelcerro
                dbfilename
109 43377 jjdelcerro
            );
110
        } else {
111 44360 omartinez
            connectionURL =  MessageFormat.format(
112 44361 jjdelcerro
                "jdbc:h2:tcp://{0}:{1,number,#######}/{2}"+commonParameters.toString(),
113 43377 jjdelcerro
                params.getHost(),
114
                params.getPort().intValue(),
115 43892 jjdelcerro
                dbfilename
116 43377 jjdelcerro
            );
117
        }
118 44198 jjdelcerro
        LOGGER.debug("connectionURL: {}", connectionURL);
119 43377 jjdelcerro
        return connectionURL;
120
    }
121
122
    private static class ConnectionProvider {
123
124
        private static boolean needRegisterDriver = true;
125
126
        private BasicDataSource dataSource = null;
127
128
        private final H2SpatialConnectionParameters connectionParameters;
129
130 43892 jjdelcerro
        private static Server server = null;
131
        private static boolean startServer = true;
132
133 43377 jjdelcerro
        public ConnectionProvider(H2SpatialConnectionParameters connectionParameters) {
134
            this.connectionParameters = connectionParameters;
135
        }
136 43892 jjdelcerro
137
        private void startServer() {
138
139
            if( startServer && server == null ) {
140
                String port = "9123";
141
                try {
142 44346 jjdelcerro
                    Server theServer;
143
                    String s = System.getProperty("H2Port");
144
                    if( s!=null ) {
145
                        try {
146
                            int n = Integer.parseInt(s);
147
                            port = String.valueOf(n);
148
                        } catch(Throwable th) {
149
                            // Ignore port number, use default.
150
                        }
151
                    }
152
                    if( System.getProperty("H2AllowOthers")!=null ) {
153
                        theServer = Server.createTcpServer("-tcpPort", port, "-tcpAllowOthers", "-ifExists");
154
                    } else {
155
                        theServer = Server.createTcpServer("-tcpPort", port, "-ifExists");
156
                    }
157 43892 jjdelcerro
                    theServer.start();
158
                    server = theServer;
159 44198 jjdelcerro
                    LOGGER.info("H2 Server started" );
160
                    LOGGER.info("  port  :"+ server.getPort());
161 44346 jjdelcerro
                    LOGGER.info("  URL  :"+ server.getURL());
162 44198 jjdelcerro
                    LOGGER.info("  status:"+ server.getStatus());
163 43892 jjdelcerro
                } catch (SQLException ex) {
164 44198 jjdelcerro
                    LOGGER.warn("H2 Server not started",ex);
165 43892 jjdelcerro
                }
166
                // Tanto si consigue lanzar el server como si no, no lo vuelve a intentar
167
                startServer = false;
168
            }
169 43377 jjdelcerro
170 43892 jjdelcerro
        }
171
172 43649 jjdelcerro
        @Override
173
        public String toString() {
174
            StringBuilder builder = new StringBuilder();
175
            builder.append(" url=").append(connectionParameters.getUrl());
176
            builder.append(" driver name=").append(connectionParameters.getJDBCDriverClassName());
177
            builder.append(" user=").append(connectionParameters.getUser());
178
            return builder.toString();
179
        }
180
181 43377 jjdelcerro
        public Connection getConnection() throws SQLException {
182
            if (this.dataSource == null) {
183
                this.dataSource = this.createDataSource();
184
            }
185
            Connection conn = this.dataSource.getConnection();
186
            try {
187
                conn.createStatement().execute("SELECT TOP 1 SRID FROM SPATIAL_REF_SYS");
188
            } catch(SQLException ex) {
189
                H2GISExtension.load(conn);
190
            }
191 44360 omartinez
            try {
192
                conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS PUBLIC;SET SCHEMA PUBLIC");
193
            } catch(SQLException ex) {
194 44361 jjdelcerro
                // Ignore this error.
195 44360 omartinez
            }
196 44361 jjdelcerro
197 43377 jjdelcerro
            return conn;
198
        }
199
200
        private BasicDataSource createDataSource() throws SQLException {
201
            if (!this.isRegistered()) {
202
                this.registerDriver();
203
            }
204 43892 jjdelcerro
            startServer();
205 43377 jjdelcerro
            H2SpatialConnectionParameters params = connectionParameters;
206
207
            BasicDataSource ds = new BasicDataSource();
208
            ds.setDriverClassName(params.getJDBCDriverClassName());
209
            if( !StringUtils.isEmpty(params.getUser()) ) {
210
                ds.setUsername(params.getUser());
211
            }
212
            if( !StringUtils.isEmpty(params.getPassword()) ) {
213
                ds.setPassword(params.getPassword());
214
            }
215
            ds.setUrl(params.getUrl());
216
217
            ds.setMaxWait(60L * 1000);
218
            return ds;
219
        }
220
221
        private boolean isRegistered() {
222
            return needRegisterDriver;
223
        }
224
225
        public void registerDriver() throws SQLException {
226
            String className = this.connectionParameters.getJDBCDriverClassName();
227
            if (className == null) {
228
                return;
229
            }
230
            try {
231
                Class theClass = Class.forName(className);
232
                if (theClass == null) {
233
                    throw new JDBCDriverClassNotFoundException(H2SpatialLibrary.NAME, className);
234
                }
235
            } catch (Exception e) {
236
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
237
            }
238
            needRegisterDriver = false;
239
        }
240
241
    }
242
243
    private ConnectionProvider connectionProvider = null;
244
245
    public H2SpatialHelper(JDBCConnectionParameters connectionParameters) {
246
        super(connectionParameters);
247 43606 jjdelcerro
        this.srssolver = new SRSSolverBase(this);
248 43377 jjdelcerro
    }
249
250
    @Override
251
    public synchronized Connection  getConnection() throws AccessResourceException {
252
        try {
253
            if (this.connectionProvider == null) {
254
                this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
255
            }
256
            Connection connection = this.connectionProvider.getConnection();
257 44198 jjdelcerro
            if( LOGGER.isDebugEnabled() ) {
258
                LOGGER.debug("getConnection: connection = "+connection.hashCode()+ connectionProvider.toString());
259 43649 jjdelcerro
            }
260 43377 jjdelcerro
            return connection;
261
        } catch (SQLException ex) {
262
            throw new AccessResourceException(H2SpatialLibrary.NAME, ex);
263
        }
264
    }
265
266
    @Override
267
    public void closeConnection(Connection connection) {
268 44198 jjdelcerro
        LOGGER.debug("closeConnection: connection = "+connection.hashCode());
269 43377 jjdelcerro
        super.closeConnection(connection);
270
    }
271
272
    @Override
273
    public H2SpatialConnectionParameters getConnectionParameters() {
274
        return (H2SpatialConnectionParameters) super.getConnectionParameters();
275
    }
276
277
    @Override
278
    public String getConnectionURL() {
279
        return getConnectionURL(this.getConnectionParameters());
280
    }
281
282
    @Override
283
    protected String getResourceType() {
284
        return H2SpatialLibrary.NAME;
285
    }
286
287
    @Override
288
    public String getProviderName() {
289
        return H2SpatialLibrary.NAME;
290
    }
291
292
    @Override
293
    public JDBCSQLBuilderBase createSQLBuilder() {
294
        return new H2SpatialSQLBuilder(this);
295
    }
296
297
    @Override
298
    public OperationsFactory getOperations() {
299
        if (this.operationsFactory == null) {
300
            this.operationsFactory = new H2SpatialOperationsFactory(this);
301
        }
302
        return operationsFactory;
303
    }
304
305
    @Override
306 44198 jjdelcerro
    public GeometrySupportType getGeometrySupportType() {
307
        return GeometrySupportType.WKB;
308 43377 jjdelcerro
    }
309
310
    @Override
311
    public boolean hasSpatialFunctions() {
312
        return true;
313
    }
314
315
    @Override
316
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
317
        return true;
318
    }
319
320
    @Override
321
    public String getQuoteForIdentifiers() {
322
        return "\"";
323
    }
324
325
    @Override
326
    public boolean allowAutomaticValues() {
327
        return true;
328
    }
329
330
    @Override
331
    public boolean supportOffsetInSelect() {
332
        return true;
333
    }
334
335
    @Override
336
    public String getQuoteForStrings() {
337
        return "'";
338
    }
339
340
    @Override
341
    public String getSourceId(JDBCStoreParameters parameters) {
342
        return parameters.getDBName() + "." +
343
               parameters.getSchema()+ "." +
344
               parameters.getTable();
345
    }
346
347
    @Override
348
    public JDBCNewStoreParameters createNewStoreParameters() {
349
        return new H2SpatialNewStoreParameters();
350
    }
351
352
    @Override
353
    public JDBCStoreParameters createOpenStoreParameters() {
354
        return new H2SpatialStoreParameters();
355
    }
356
357
    @Override
358
    public JDBCServerExplorerParameters createServerExplorerParameters() {
359
        return new H2SpatialExplorerParameters();
360
    }
361
362 44160 jjdelcerro
    @Override
363
    public JDBCServerExplorer createServerExplorer(
364
            JDBCServerExplorerParameters parameters,
365
            DataServerExplorerProviderServices providerServices
366
        ) throws InitializeException {
367
368
        JDBCServerExplorer explorer = new JDBCServerExplorerBase(
369
                parameters,
370
                providerServices,
371
                this
372
        );
373
        this.initialize(explorer, parameters, null);
374
        return explorer;
375
    }
376 43377 jjdelcerro
}