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.mdb / src / main / java / org / gvsig / fmap / dal / store / mdb / MDBHelper.java @ 45647

History | View | Annotate | Download (15.9 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.fmap.dal.store.mdb;
23

    
24
import java.io.File;
25
import java.sql.Clob;
26
import java.sql.Connection;
27
import java.sql.ResultSet;
28
import java.sql.SQLException;
29
import java.text.MessageFormat;
30
import org.apache.commons.dbcp.BasicDataSource;
31
import org.apache.commons.io.IOUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.exception.InitializeException;
36
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
37
import org.gvsig.fmap.dal.spi.DataServerExplorerProviderServices;
38
import org.gvsig.fmap.dal.store.mdb.operations.MDBOperationsFactory;
39
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
40
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
41
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
42
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
43
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCCantFetchValueException;
44
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCDriverClassNotFoundException;
45
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
46
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
47
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
48
import org.gvsig.fmap.dal.store.jdbc2.spi.ConnectionProvider;
49
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
50
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
51
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCServerExplorerBase;
52
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverDumb;
53
import org.gvsig.fmap.geom.Geometry;
54
//import org.h2.tools.Server;
55
//import org.h2gis.ext.H2GISExtension;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58

    
59
@SuppressWarnings("UseSpecificCatch")
60
public class MDBHelper extends JDBCHelperBase {
61

    
62
    static final Logger LOGGER = LoggerFactory.getLogger(MDBHelper.class);
63

    
64
    public static final String MDB_JDBC_DRIVER = "net.ucanaccess.jdbc.UcanaccessDriver";
65

    
66
    public static String getConnectionURL(MDBConnectionParameters params) {
67
        String connectionURL;
68
        String dbfilename = params.getFile().getAbsolutePath().replace("\\","/");
69
//        if( dbfilename!=null && dbfilename.endsWith(".mdb") ) {
70
//            dbfilename = dbfilename.substring(0, dbfilename.length()-3);
71
//        }
72
        StringBuilder commonParameters = new StringBuilder();
73
//        commonParameters.append(";MODE=PostgreSQL");
74
//        commonParameters.append(";SCHEMA=PUBLIC");
75
        
76
//        Integer LOCK_TIMEOUT = (Integer) params.getDynValue("LOCK_TIMEOUT");
77
//        if( LOCK_TIMEOUT!=null ) {
78
//            commonParameters.append(";LOCK_TIMEOUT=").append(LOCK_TIMEOUT);
79
//        }
80
//        Integer MULTI_THREADED = (Integer) params.getDynValue("MULTI_THREADED");
81
//        if( MULTI_THREADED!=null ) {
82
//            commonParameters.append(";MULTI_THREADED=").append(MULTI_THREADED);
83
//        }
84
//        Integer CHACHE_SIZE = (Integer) params.getDynValue("CHACHE_SIZE");
85
//        if( LOCK_TIMEOUT!=null ) {
86
//            commonParameters.append(";CHACHE_SIZE=").append(CHACHE_SIZE);
87
//        }
88
//        Integer LOG = (Integer) params.getDynValue("LOG");
89
//        if( LOCK_TIMEOUT!=null ) {
90
//            commonParameters.append(";LOG=").append(LOG);
91
//        }
92
//        Integer LOCK_MODE = (Integer) params.getDynValue("LOCK_MODE");
93
//        if( LOCK_TIMEOUT!=null ) {
94
//            commonParameters.append(";LOCK_MODE=").append(LOCK_MODE);
95
//        }
96
        if (!params.getFile().exists()) {
97
            commonParameters.append("newdatabaseversion=V2010;");
98
        }
99
        commonParameters.append("showSchema=true;");
100
        
101
        // http://ucanaccess.sourceforge.net/site.html#examples
102
        connectionURL =  MessageFormat.format(                
103
                "jdbc:ucanaccess://{0};"+commonParameters.toString(),
104
                dbfilename
105
        );
106
        
107
        LOGGER.debug("connectionURL: {}", connectionURL);
108
        return connectionURL;
109
    }
110

    
111
    public static class ConnectionProviderImpl implements ConnectionProvider {
112

    
113
        private static boolean needRegisterDriver = true;
114

    
115
        private BasicDataSource dataSource = null;
116

    
117
        private final MDBConnectionParameters connectionParameters;
118

    
119
//        private static Server server = null;
120
        private static String server = null;
121
        private static boolean startServer = true;
122

    
123
        public ConnectionProviderImpl(MDBConnectionParameters connectionParameters) {
124
            this.connectionParameters = connectionParameters;
125
        }
126
        
127
        @Override
128
        public String getStatus() {
129
            StringBuilder builder = new StringBuilder();
130
            builder.append("Pool: ");
131
            builder.append(JDBCUtils.getHexId(dataSource));
132
            builder.append(" Actives: ");
133
            builder.append(dataSource.getNumActive());
134
            builder.append("/");
135
            builder.append(dataSource.getMaxActive());
136
            builder.append(" idle: ");
137
            builder.append(dataSource.getNumIdle());
138
            builder.append("/");
139
            builder.append(dataSource.getMinIdle());
140
            builder.append(":");
141
            builder.append(dataSource.getMaxIdle());
142
            return builder.toString();
143
        }
144

    
145
        
146
        public static void stopServer() {
147
          try {
148
//            server.shutdown();
149
          } catch(Throwable th) {
150
            
151
          }
152
          try {
153
//            server.stop();
154
          } catch(Throwable th) {
155
            
156
          }
157
//          server = null;
158
          startServer = true;
159
          LOGGER.info("MDB Server stopped" );
160
        }
161
        
162
        private void startServer() {
163
        
164
            if( startServer && server == null ) {
165
                String port = "9123";
166
//                Server theServer;
167
                String s = System.getProperty("MDBPort");
168
                if( s!=null ) {
169
                    try {
170
                        int n = Integer.parseInt(s);
171
                        port = String.valueOf(n);
172
                    } catch(Throwable th) {
173
                        // Ignore port number, use default.
174
                    }
175
                }
176
                if( System.getProperty("MDBAllowOthers")!=null ) {
177
//                    theServer = Server.createTcpServer("-tcpPort", port, "-tcpAllowOthers", "-ifExists");
178
                } else {
179
//                    theServer = Server.createTcpServer("-tcpPort", port, "-ifExists");
180
                }
181
//                theServer.start();
182
//                server = theServer;
183
                LOGGER.info("MDB Server started" );
184
//                LOGGER.info("  port  :"+ server.getPort());
185
//                LOGGER.info("  URL  :"+ server.getURL());
186
//                LOGGER.info("  status:"+ server.getStatus());
187
                // Tanto si consigue lanzar el server como si no, no lo vuelve a intentar
188
                startServer = false;
189
            }
190

    
191
        }
192

    
193
        @Override
194
        public String toString() {
195
            StringBuilder builder = new StringBuilder();
196
            builder.append(" url=").append(connectionParameters.getUrl());
197
            builder.append(" driver name=").append(connectionParameters.getJDBCDriverClassName());
198
            builder.append(" user=").append(connectionParameters.getUser());
199
            return builder.toString();
200
        }
201
        
202
        public Connection getConnection() throws SQLException {
203
            File f = this.connectionParameters.getFile();
204
            boolean newdb = f!=null && !f.exists();
205
            
206
            if (this.dataSource == null) {
207
                this.dataSource = this.createDataSource();               
208
            }
209
            Connection conn = this.dataSource.getConnection();
210
////            try {
211
//////                conn.createStatement().execute("SELECT TOP 1 SRID FROM SPATIAL_REF_SYS");
212
////            } catch(SQLException ex) {
213
//////                H2GISExtension.load(conn);
214
////            }
215
//            try {
216
////                conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS PUBLIC;SET SCHEMA PUBLIC");
217
//            } catch(SQLException ex) {
218
//                // Ignore this error.
219
//            }
220
            if (newdb) {
221
                //crea tablas
222
                //
223
            }
224
            return conn;
225
        }
226

    
227
        private BasicDataSource createDataSource() throws SQLException {
228
            if (!this.isRegistered()) {
229
                this.registerDriver();
230
            }
231
            startServer();
232
            MDBConnectionParameters params = connectionParameters;
233

    
234
            BasicDataSource ds = new BasicDataSource();
235
            ds.setDriverClassName(params.getJDBCDriverClassName());
236
            if( !StringUtils.isEmpty(params.getUser()) ) {
237
                ds.setUsername(params.getUser());
238
            }
239
            if( !StringUtils.isEmpty(params.getPassword()) ) {
240
                ds.setPassword(params.getPassword());
241
            }
242
            ds.setUrl(params.getUrl());
243

    
244
            ds.setMaxWait(60L * 1000);
245
            return ds;
246
        }
247

    
248
        private boolean isRegistered() {
249
            return needRegisterDriver;
250
        }
251

    
252
        public void registerDriver() throws SQLException {
253
            String className = this.connectionParameters.getJDBCDriverClassName();
254
            if (className == null) {
255
                return;
256
            }
257
            try {
258
                Class theClass = Class.forName(className);
259
                if (theClass == null) {
260
                    throw new JDBCDriverClassNotFoundException(MDBLibrary.NAME, className);
261
                }
262
            } catch (Exception e) {
263
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
264
            }
265
            needRegisterDriver = false;
266
        }
267

    
268
    }
269

    
270
    private ConnectionProvider connectionProvider = null;
271
    
272
        /**
273
     * Constructor for use only for testing purposes.
274
     * 
275
     * @param connectionParameters
276
     * @param connectionProvider
277
     */
278
    public MDBHelper(JDBCConnectionParameters connectionParameters, ConnectionProvider connectionProvider) { 
279
        super(connectionParameters);
280
        this.srssolver = new SRSSolverDumb(this);
281
        this.connectionProvider = connectionProvider;
282
    }
283
 
284
    public MDBHelper(JDBCConnectionParameters connectionParameters) {
285
        super(connectionParameters);
286
        this.srssolver = new SRSSolverDumb(this);
287
    }
288

    
289
    @Override
290
    public synchronized Connection  getConnection() throws AccessResourceException {
291
        try {
292
            if (this.connectionProvider == null) {
293
              MDBConnectionParameters connectionParameters = this.getConnectionParameters();
294
              if( connectionParameters==null ) {
295
                return null; // Testing mode?
296
              }
297
              this.connectionProvider = new ConnectionProviderImpl(connectionParameters);
298
            }
299
            Connection connection = this.connectionProvider.getConnection();
300
            if( LOGGER.isDebugEnabled() ) {
301
                LOGGER.debug("getConnection: connection = "+connection.hashCode()+ connectionProvider.toString());
302
            }
303
            return connection;
304
        } catch (SQLException ex) {
305
            throw new AccessResourceException(MDBLibrary.NAME, ex);
306
        }
307
    }
308

    
309
    @Override
310
    public void closeConnection(Connection connection) {
311
      if( connection!=null ) { // In test ???
312
        LOGGER.debug("closeConnection: connection = "+connection.hashCode());
313
      }
314
      super.closeConnection(connection);
315
    }
316
    
317
    @Override
318
    public MDBConnectionParameters getConnectionParameters() {
319
        return (MDBConnectionParameters) super.getConnectionParameters();
320
    }
321
    
322
    @Override
323
    public String getConnectionURL() {
324
        return getConnectionURL(this.getConnectionParameters());
325
    }
326

    
327
    @Override
328
    protected String getResourceType() {
329
        return MDBLibrary.NAME;
330
    }
331

    
332
    @Override
333
    public String getProviderName() {
334
        return MDBLibrary.NAME;
335
    }
336

    
337
    @Override
338
    public JDBCSQLBuilderBase createSQLBuilder() {
339
        return new MDBSQLBuilder(this);
340
    }
341
    
342
    @Override
343
    public OperationsFactory getOperations() {
344
        if (this.operationsFactory == null) {
345
            this.operationsFactory = new MDBOperationsFactory(this);
346
        }
347
        return operationsFactory;
348
    }
349

    
350
    @Override
351
    public GeometrySupportType getGeometrySupportType() {
352
        return GeometrySupportType.WKB;
353
    }
354

    
355
    @Override
356
    public boolean hasSpatialFunctions() {
357
        return false;
358
    }
359

    
360
    @Override
361
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
362
        return true;
363
    }
364

    
365
    @Override
366
    public String getQuoteForIdentifiers() {
367
        return "\"";
368
    }
369

    
370
    @Override
371
    public boolean allowAutomaticValues() {
372
        return true;
373
    }
374

    
375
    @Override
376
    public boolean supportOffsetInSelect() {
377
        return true;
378
    }
379

    
380
    @Override
381
    public String getQuoteForStrings() {
382
        return "'";
383
    }
384

    
385
    @Override
386
    public String getSourceId(JDBCStoreParameters parameters) {
387
        return parameters.getDBName() + "." + 
388
               parameters.getSchema()+ "." + 
389
               parameters.getTable();
390
    }
391

    
392
    @Override
393
    public JDBCNewStoreParameters createNewStoreParameters() {
394
        return new MDBNewStoreParameters();
395
    }
396

    
397
    @Override
398
    public JDBCStoreParameters createOpenStoreParameters() {
399
        return new MDBStoreParameters();
400
    }
401

    
402
    @Override
403
    public JDBCServerExplorerParameters createServerExplorerParameters() {
404
        return new MDBExplorerParameters();
405
    }
406

    
407
    @Override
408
    public JDBCServerExplorer createServerExplorer(
409
            JDBCServerExplorerParameters parameters, 
410
            DataServerExplorerProviderServices providerServices
411
        ) throws InitializeException {
412
        
413
        JDBCServerExplorer explorer = new JDBCServerExplorerBase(
414
                parameters, 
415
                providerServices, 
416
                this
417
        );
418
        this.initialize(explorer, parameters, null);
419
        return explorer;
420
    }
421
    
422
    @Override
423
  public Geometry getGeometryFromColumn(ResultSet rs, int index) throws DataException {
424
    try {
425
      Object value;
426
      Clob clob;
427
      String strGeom;
428
      switch (this.getGeometrySupportType()) {
429
        case NATIVE:
430
        case WKB:
431
            clob = rs.getClob(index);
432
            if (clob ==null) {
433
                return null;
434
            }
435
            strGeom = new String(IOUtils.toCharArray(clob.getCharacterStream()));
436
            clob.free();
437
            return this.getGeometryManager().createFrom(strGeom);
438
        case EWKB:
439
            clob = rs.getClob(index);
440
            if (clob ==null) {
441
                return null;
442
            }
443
            strGeom = new String(IOUtils.toCharArray(clob.getCharacterStream()));
444
            clob.free();
445
            return this.getGeometryManager().createFrom(strGeom);
446
        case WKT:
447
        default:
448
          value = rs.getString(index);
449
          if (value == null) {
450
            return null;
451
          }
452
          return this.getGeometryManager().createFrom((String) value);
453

    
454
      }
455
    } catch (Exception ex) {
456
      throw new JDBCCantFetchValueException(ex);
457
    }
458
  }
459
}