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 | } |