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

History | View | Annotate | Download (14.8 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.OperationsFactory;
47
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase;
48
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
49
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCServerExplorerBase;
50
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverDumb;
51
import org.gvsig.fmap.geom.Geometry;
52
//import org.h2.tools.Server;
53
//import org.h2gis.ext.H2GISExtension;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

    
57
@SuppressWarnings("UseSpecificCatch")
58
public class MDBHelper extends JDBCHelperBase {
59

    
60
    static final Logger LOGGER = LoggerFactory.getLogger(MDBHelper.class);
61

    
62
    public static final String MDB_JDBC_DRIVER = "net.ucanaccess.jdbc.UcanaccessDriver";
63

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

    
109
    public static class ConnectionProvider {
110

    
111
        private static boolean needRegisterDriver = true;
112

    
113
        private BasicDataSource dataSource = null;
114

    
115
        private final MDBConnectionParameters connectionParameters;
116

    
117
//        private static Server server = null;
118
        private static String server = null;
119
        private static boolean startServer = true;
120

    
121
        public ConnectionProvider(MDBConnectionParameters connectionParameters) {
122
            this.connectionParameters = connectionParameters;
123
        }
124
        
125
        public static void stopServer() {
126
          try {
127
//            server.shutdown();
128
          } catch(Throwable th) {
129
            
130
          }
131
          try {
132
//            server.stop();
133
          } catch(Throwable th) {
134
            
135
          }
136
//          server = null;
137
          startServer = true;
138
          LOGGER.info("MDB Server stopped" );
139
        }
140
        
141
        private void startServer() {
142
        
143
            if( startServer && server == null ) {
144
                String port = "9123";
145
//                Server theServer;
146
                String s = System.getProperty("MDBPort");
147
                if( s!=null ) {
148
                    try {
149
                        int n = Integer.parseInt(s);
150
                        port = String.valueOf(n);
151
                    } catch(Throwable th) {
152
                        // Ignore port number, use default.
153
                    }
154
                }
155
                if( System.getProperty("MDBAllowOthers")!=null ) {
156
//                    theServer = Server.createTcpServer("-tcpPort", port, "-tcpAllowOthers", "-ifExists");
157
                } else {
158
//                    theServer = Server.createTcpServer("-tcpPort", port, "-ifExists");
159
                }
160
//                theServer.start();
161
//                server = theServer;
162
                LOGGER.info("MDB Server started" );
163
//                LOGGER.info("  port  :"+ server.getPort());
164
//                LOGGER.info("  URL  :"+ server.getURL());
165
//                LOGGER.info("  status:"+ server.getStatus());
166
                // Tanto si consigue lanzar el server como si no, no lo vuelve a intentar
167
                startServer = false;
168
            }
169

    
170
        }
171

    
172
        @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
        public Connection getConnection() throws SQLException {
182
            File f = this.connectionParameters.getFile();
183
            boolean newdb = f!=null && !f.exists();
184
            
185
            if (this.dataSource == null) {
186
                this.dataSource = this.createDataSource();               
187
            }
188
            Connection conn = this.dataSource.getConnection();
189
////            try {
190
//////                conn.createStatement().execute("SELECT TOP 1 SRID FROM SPATIAL_REF_SYS");
191
////            } catch(SQLException ex) {
192
//////                H2GISExtension.load(conn);
193
////            }
194
//            try {
195
////                conn.createStatement().execute("CREATE SCHEMA IF NOT EXISTS PUBLIC;SET SCHEMA PUBLIC");
196
//            } catch(SQLException ex) {
197
//                // Ignore this error.
198
//            }
199
            if (newdb) {
200
                //crea tablas
201
                //
202
            }
203
            return conn;
204
        }
205

    
206
        private BasicDataSource createDataSource() throws SQLException {
207
            if (!this.isRegistered()) {
208
                this.registerDriver();
209
            }
210
            startServer();
211
            MDBConnectionParameters params = connectionParameters;
212

    
213
            BasicDataSource ds = new BasicDataSource();
214
            ds.setDriverClassName(params.getJDBCDriverClassName());
215
            if( !StringUtils.isEmpty(params.getUser()) ) {
216
                ds.setUsername(params.getUser());
217
            }
218
            if( !StringUtils.isEmpty(params.getPassword()) ) {
219
                ds.setPassword(params.getPassword());
220
            }
221
            ds.setUrl(params.getUrl());
222

    
223
            ds.setMaxWait(60L * 1000);
224
            return ds;
225
        }
226

    
227
        private boolean isRegistered() {
228
            return needRegisterDriver;
229
        }
230

    
231
        public void registerDriver() throws SQLException {
232
            String className = this.connectionParameters.getJDBCDriverClassName();
233
            if (className == null) {
234
                return;
235
            }
236
            try {
237
                Class theClass = Class.forName(className);
238
                if (theClass == null) {
239
                    throw new JDBCDriverClassNotFoundException(MDBLibrary.NAME, className);
240
                }
241
            } catch (Exception e) {
242
                throw new SQLException("Can't register JDBC driver '" + className + "'.", e);
243
            }
244
            needRegisterDriver = false;
245
        }
246

    
247
    }
248

    
249
    private ConnectionProvider connectionProvider = null;
250
 
251
    /**
252
     * Constructor for use only for testing purposes.
253
     */
254
    public MDBHelper() { 
255
        super(null);
256
    }
257
  
258
    public MDBHelper(JDBCConnectionParameters connectionParameters) {
259
        super(connectionParameters);
260
        this.srssolver = new SRSSolverDumb(this);
261
    }
262

    
263
    @Override
264
    public synchronized Connection  getConnection() throws AccessResourceException {
265
        try {
266
            if (this.connectionProvider == null) {
267
              MDBConnectionParameters connectionParameters = this.getConnectionParameters();
268
              if( connectionParameters==null ) {
269
                return null; // Testing mode?
270
              }
271
              this.connectionProvider = new ConnectionProvider(connectionParameters);
272
            }
273
            Connection connection = this.connectionProvider.getConnection();
274
            if( LOGGER.isDebugEnabled() ) {
275
                LOGGER.debug("getConnection: connection = "+connection.hashCode()+ connectionProvider.toString());
276
            }
277
            return connection;
278
        } catch (SQLException ex) {
279
            throw new AccessResourceException(MDBLibrary.NAME, ex);
280
        }
281
    }
282

    
283
    @Override
284
    public void closeConnection(Connection connection) {
285
      if( connection!=null ) { // In test ???
286
        LOGGER.debug("closeConnection: connection = "+connection.hashCode());
287
      }
288
      super.closeConnection(connection);
289
    }
290
    
291
    @Override
292
    public MDBConnectionParameters getConnectionParameters() {
293
        return (MDBConnectionParameters) super.getConnectionParameters();
294
    }
295
    
296
    @Override
297
    public String getConnectionURL() {
298
        return getConnectionURL(this.getConnectionParameters());
299
    }
300

    
301
    @Override
302
    protected String getResourceType() {
303
        return MDBLibrary.NAME;
304
    }
305

    
306
    @Override
307
    public String getProviderName() {
308
        return MDBLibrary.NAME;
309
    }
310

    
311
    @Override
312
    public JDBCSQLBuilderBase createSQLBuilder() {
313
        return new MDBSQLBuilder(this);
314
    }
315
    
316
    @Override
317
    public OperationsFactory getOperations() {
318
        if (this.operationsFactory == null) {
319
            this.operationsFactory = new MDBOperationsFactory(this);
320
        }
321
        return operationsFactory;
322
    }
323

    
324
    @Override
325
    public GeometrySupportType getGeometrySupportType() {
326
        return GeometrySupportType.WKB;
327
    }
328

    
329
    @Override
330
    public boolean hasSpatialFunctions() {
331
        return false;
332
    }
333

    
334
    @Override
335
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
336
        return true;
337
    }
338

    
339
    @Override
340
    public String getQuoteForIdentifiers() {
341
        return "\"";
342
    }
343

    
344
    @Override
345
    public boolean allowAutomaticValues() {
346
        return true;
347
    }
348

    
349
    @Override
350
    public boolean supportOffsetInSelect() {
351
        return true;
352
    }
353

    
354
    @Override
355
    public String getQuoteForStrings() {
356
        return "'";
357
    }
358

    
359
    @Override
360
    public String getSourceId(JDBCStoreParameters parameters) {
361
        return parameters.getDBName() + "." + 
362
               parameters.getSchema()+ "." + 
363
               parameters.getTable();
364
    }
365

    
366
    @Override
367
    public JDBCNewStoreParameters createNewStoreParameters() {
368
        return new MDBNewStoreParameters();
369
    }
370

    
371
    @Override
372
    public JDBCStoreParameters createOpenStoreParameters() {
373
        return new MDBStoreParameters();
374
    }
375

    
376
    @Override
377
    public JDBCServerExplorerParameters createServerExplorerParameters() {
378
        return new MDBExplorerParameters();
379
    }
380

    
381
    @Override
382
    public JDBCServerExplorer createServerExplorer(
383
            JDBCServerExplorerParameters parameters, 
384
            DataServerExplorerProviderServices providerServices
385
        ) throws InitializeException {
386
        
387
        JDBCServerExplorer explorer = new JDBCServerExplorerBase(
388
                parameters, 
389
                providerServices, 
390
                this
391
        );
392
        this.initialize(explorer, parameters, null);
393
        return explorer;
394
    }
395
    
396
    @Override
397
  public Geometry getGeometryFromColumn(ResultSet rs, int index) throws DataException {
398
    try {
399
      Object value;
400
      Clob clob;
401
      String strGeom;
402
      switch (this.getGeometrySupportType()) {
403
        case NATIVE:
404
        case WKB:
405
            clob = rs.getClob(index);
406
            if (clob ==null) {
407
                return null;
408
            }
409
            strGeom = new String(IOUtils.toCharArray(clob.getCharacterStream()));
410
            clob.free();
411
            return this.getGeometryManager().createFrom(strGeom);
412
        case EWKB:
413
            clob = rs.getClob(index);
414
            if (clob ==null) {
415
                return null;
416
            }
417
            strGeom = new String(IOUtils.toCharArray(clob.getCharacterStream()));
418
            return this.getGeometryManager().createFrom(strGeom);
419
        case WKT:
420
        default:
421
          value = rs.getString(index);
422
          if (value == null) {
423
            return null;
424
          }
425
          return this.getGeometryManager().createFrom((String) value);
426

    
427
      }
428
    } catch (Exception ex) {
429
      throw new JDBCCantFetchValueException(ex);
430
    }
431
  }
432
}