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 @ 44198

History | View | Annotate | Download (11.4 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 43377 jjdelcerro
        if( StringUtils.isEmpty(params.getHost()) ) {
65
            // Asumimos que es una conexion directa sobre el filesystem
66
            if( StringUtils.equalsIgnoreCase(FilenameUtils.getExtension(params.getFile().getName()),"zip") ) {
67
                connectionURL =  MessageFormat.format(
68
                    "jdbc:h2:zip:{0}!/{1};MODE=PostgreSQL",
69 43892 jjdelcerro
                    dbfilename,
70 43377 jjdelcerro
                    params.getDBName()
71
                );
72
            } else {
73
                connectionURL =  MessageFormat.format(
74
                    "jdbc:h2:file:{0};MODE=PostgreSQL",
75 43892 jjdelcerro
                    dbfilename
76 43377 jjdelcerro
                );
77
            }
78
        } else if( params.getPort() == null ) {
79
            connectionURL =  MessageFormat.format(
80
                "jdbc:h2:tcp://{0}/{1};MODE=PostgreSQL",
81
                params.getHost(),
82 43892 jjdelcerro
                dbfilename
83 43377 jjdelcerro
            );
84
        } else {
85
            connectionURL =  MessageFormat.format(
86
                "jdbc:h2:tcp://{0}:{1,number,#######}/{2};MODE=PostgreSQL",
87
                params.getHost(),
88
                params.getPort().intValue(),
89 43892 jjdelcerro
                dbfilename
90 43377 jjdelcerro
            );
91
        }
92 44198 jjdelcerro
        LOGGER.debug("connectionURL: {}", connectionURL);
93 43377 jjdelcerro
        return connectionURL;
94
    }
95
96
    private static class ConnectionProvider {
97
98
        private static boolean needRegisterDriver = true;
99
100
        private BasicDataSource dataSource = null;
101
102
        private final H2SpatialConnectionParameters connectionParameters;
103
104 43892 jjdelcerro
        private static Server server = null;
105
        private static boolean startServer = true;
106
107 43377 jjdelcerro
        public ConnectionProvider(H2SpatialConnectionParameters connectionParameters) {
108
            this.connectionParameters = connectionParameters;
109
        }
110 43892 jjdelcerro
111
        private void startServer() {
112
113
            if( startServer && server == null ) {
114
                String port = "9123";
115
                try {
116
                    Server theServer = Server.createTcpServer("-tcpPort", port, /*"-tcpAllowOthers",*/ "-ifExists");
117
                    theServer.start();
118
                    server = theServer;
119 44198 jjdelcerro
                    LOGGER.info("H2 Server started" );
120
                    LOGGER.info("  port  :"+ server.getPort());
121
                    LOGGER.info("  status:"+ server.getStatus());
122 43892 jjdelcerro
                } catch (SQLException ex) {
123 44198 jjdelcerro
                    LOGGER.warn("H2 Server not started",ex);
124 43892 jjdelcerro
                }
125
                // Tanto si consigue lanzar el server como si no, no lo vuelve a intentar
126
                startServer = false;
127
            }
128 43377 jjdelcerro
129 43892 jjdelcerro
        }
130
131 43649 jjdelcerro
        @Override
132
        public String toString() {
133
            StringBuilder builder = new StringBuilder();
134
            builder.append(" url=").append(connectionParameters.getUrl());
135
            builder.append(" driver name=").append(connectionParameters.getJDBCDriverClassName());
136
            builder.append(" user=").append(connectionParameters.getUser());
137
            return builder.toString();
138
        }
139
140 43377 jjdelcerro
        public Connection getConnection() throws SQLException {
141
            if (this.dataSource == null) {
142
                this.dataSource = this.createDataSource();
143
            }
144
            Connection conn = this.dataSource.getConnection();
145
            try {
146
                conn.createStatement().execute("SELECT TOP 1 SRID FROM SPATIAL_REF_SYS");
147
            } catch(SQLException ex) {
148
                H2GISExtension.load(conn);
149
            }
150
            return conn;
151
        }
152
153
        private BasicDataSource createDataSource() throws SQLException {
154
            if (!this.isRegistered()) {
155
                this.registerDriver();
156
            }
157 43892 jjdelcerro
            startServer();
158 43377 jjdelcerro
            H2SpatialConnectionParameters params = connectionParameters;
159
160
            BasicDataSource ds = new BasicDataSource();
161
            ds.setDriverClassName(params.getJDBCDriverClassName());
162
            if( !StringUtils.isEmpty(params.getUser()) ) {
163
                ds.setUsername(params.getUser());
164
            }
165
            if( !StringUtils.isEmpty(params.getPassword()) ) {
166
                ds.setPassword(params.getPassword());
167
            }
168
            ds.setUrl(params.getUrl());
169
170
            ds.setMaxWait(60L * 1000);
171
            return ds;
172
        }
173
174
        private boolean isRegistered() {
175
            return needRegisterDriver;
176
        }
177
178
        public void registerDriver() throws SQLException {
179
            String className = this.connectionParameters.getJDBCDriverClassName();
180
            if (className == null) {
181
                return;
182
            }
183
            try {
184
                Class theClass = Class.forName(className);
185
                if (theClass == null) {
186
                    throw new JDBCDriverClassNotFoundException(H2SpatialLibrary.NAME, className);
187
                }
188
            } catch (Exception e) {
189
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
190
            }
191
            needRegisterDriver = false;
192
        }
193
194
    }
195
196
    private ConnectionProvider connectionProvider = null;
197
198
    public H2SpatialHelper(JDBCConnectionParameters connectionParameters) {
199
        super(connectionParameters);
200 43606 jjdelcerro
        this.srssolver = new SRSSolverBase(this);
201 43377 jjdelcerro
    }
202
203
    @Override
204
    public synchronized Connection  getConnection() throws AccessResourceException {
205
        try {
206
            if (this.connectionProvider == null) {
207
                this.connectionProvider = new ConnectionProvider(this.getConnectionParameters());
208
            }
209
            Connection connection = this.connectionProvider.getConnection();
210 44198 jjdelcerro
            if( LOGGER.isDebugEnabled() ) {
211
                LOGGER.debug("getConnection: connection = "+connection.hashCode()+ connectionProvider.toString());
212 43649 jjdelcerro
            }
213 43377 jjdelcerro
            return connection;
214
        } catch (SQLException ex) {
215
            throw new AccessResourceException(H2SpatialLibrary.NAME, ex);
216
        }
217
    }
218
219
    @Override
220
    public void closeConnection(Connection connection) {
221 44198 jjdelcerro
        LOGGER.debug("closeConnection: connection = "+connection.hashCode());
222 43377 jjdelcerro
        super.closeConnection(connection);
223
    }
224
225
    @Override
226
    public H2SpatialConnectionParameters getConnectionParameters() {
227
        return (H2SpatialConnectionParameters) super.getConnectionParameters();
228
    }
229
230
    @Override
231
    public String getConnectionURL() {
232
        return getConnectionURL(this.getConnectionParameters());
233
    }
234
235
    @Override
236
    protected String getResourceType() {
237
        return H2SpatialLibrary.NAME;
238
    }
239
240
    @Override
241
    public String getProviderName() {
242
        return H2SpatialLibrary.NAME;
243
    }
244
245
    @Override
246
    public JDBCSQLBuilderBase createSQLBuilder() {
247
        return new H2SpatialSQLBuilder(this);
248
    }
249
250
    @Override
251
    public OperationsFactory getOperations() {
252
        if (this.operationsFactory == null) {
253
            this.operationsFactory = new H2SpatialOperationsFactory(this);
254
        }
255
        return operationsFactory;
256
    }
257
258
    @Override
259 44198 jjdelcerro
    public GeometrySupportType getGeometrySupportType() {
260
        return GeometrySupportType.WKB;
261 43377 jjdelcerro
    }
262
263
    @Override
264
    public boolean hasSpatialFunctions() {
265
        return true;
266
    }
267
268
    @Override
269
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
270
        return true;
271
    }
272
273
    @Override
274
    public String getQuoteForIdentifiers() {
275
        return "\"";
276
    }
277
278
    @Override
279
    public boolean allowAutomaticValues() {
280
        return true;
281
    }
282
283
    @Override
284
    public boolean supportOffsetInSelect() {
285
        return true;
286
    }
287
288
    @Override
289
    public String getQuoteForStrings() {
290
        return "'";
291
    }
292
293
    @Override
294
    public String getSourceId(JDBCStoreParameters parameters) {
295
        return parameters.getDBName() + "." +
296
               parameters.getSchema()+ "." +
297
               parameters.getTable();
298
    }
299
300
    @Override
301
    public JDBCNewStoreParameters createNewStoreParameters() {
302
        return new H2SpatialNewStoreParameters();
303
    }
304
305
    @Override
306
    public JDBCStoreParameters createOpenStoreParameters() {
307
        return new H2SpatialStoreParameters();
308
    }
309
310
    @Override
311
    public JDBCServerExplorerParameters createServerExplorerParameters() {
312
        return new H2SpatialExplorerParameters();
313
    }
314
315 44160 jjdelcerro
    @Override
316
    public JDBCServerExplorer createServerExplorer(
317
            JDBCServerExplorerParameters parameters,
318
            DataServerExplorerProviderServices providerServices
319
        ) throws InitializeException {
320
321
        JDBCServerExplorer explorer = new JDBCServerExplorerBase(
322
                parameters,
323
                providerServices,
324
                this
325
        );
326
        this.initialize(explorer, parameters, null);
327
        return explorer;
328
    }
329 43377 jjdelcerro
}