Project

General

Profile

Download (16 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2009 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9

    
10
package eu.etaxonomy.cdm.io.common;
11

    
12
/*
13
 * Created on 14.05.2005
14
 * @author Andreas Müller
15
 * Updated 20.08.2006
16
 */
17

    
18

    
19
import java.io.PrintWriter;
20
import java.sql.Connection;
21
import java.sql.DriverManager;
22
import java.sql.ResultSet;
23
import java.sql.SQLException;
24
import java.sql.Statement;
25

    
26
import org.apache.http.MethodNotSupportedException;
27
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
28

    
29
import eu.etaxonomy.cdm.database.ICdmDataSource;
30
import eu.etaxonomy.cdm.database.update.DatabaseTypeNotSupportedException;
31

    
32

    
33
/**
34
 *
35
 *  Creates Cursors from extern relational DB.
36
 *  Used only for developpers convienence hence undocumented.
37
 *  You may create input cursors in any other way you want
38
 *  @author Andreas Müller
39
 */
40
public class Source {
41
	static Logger logger = LogManager.getLogger(Source.class);
42

    
43
/* ************ Constants **************************************/
44
    //Mode
45
	private final static boolean DEBUG_MODE = false;
46
    private final static boolean DEBUG_LOG_WRITER = false;
47

    
48
    //DB info
49
//	public final static String SQL_SERVER_2000 = "SQLServer2000";
50
	public final static String SQL_SERVER_2005 = "SQLServer2005";
51
	public final static String SQL_SERVER_2008 = "SQLServer2008";
52
	public final static String ACCESS = "Access";
53
	public final static String EXCEL = "Excel";
54
	public final static String ODDBC = "ODBC";
55
	public final static String ORACLE = "Oracle";
56
	public final static String DB2 = "DB2";
57
	public final static String POSTGRESQL9 = "PostgreSQL9";
58
	public final static String MYSQL = "MySQL";
59

    
60

    
61
	//coursor mode
62
	public final static String SELECT_DIRECT = "direct";
63
	public final static String SELECT_CURSOR = "cursor";
64

    
65
    //driver class
66
//    private static String clsSQLServer2000 = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
67
    private static String clsSQLServer2005 = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
68
    private static String clsSQLServer2008 = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
69
    private static String clsODBC = "sun.jdbc.odbc.JdbcOdbcDriver";
70
    private static String clsOracle = "oracle.jdbc.driver.OracleDriver";
71
    private static String clsDB2 = "COM.ibm.db2.jdbc.net.DB2Driver";
72
    private static String clsSQLServerDdtek = "com.ddtek.jdbc.sqlserver.SQLServerDriver";
73
    private static String clsDefault = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
74
    private static String clsPostgreSQL = "org.postgresql.Driver";
75
    private static String clsMySQL = "com.mysql.cj.jdbc.Driver";
76

    
77
    //url
78
//    private static String urlSQLServer = "jdbc:microsoft:sqlserver://";
79
    private static String urlSQLServer2005 = "jdbc:sqlserver://";
80
    private static String urlSQLServer2008 = "jdbc:sqlserver://";
81
    private static String urlDB2 = "jdbc:db2://";
82
    private static String urlOracle = "jdbc:oracle:thin:@:1243:";
83
    private static String urlDataDirectSQLServer = "jdbc:datadirect:sqlserver://";
84
    private static String urlODBC = "jdbc:odbc:";
85
    private static String urlPostgreSQL = "jdbc:postgresql://";
86
    private static String urlMySQL = "jdbc:mysql://";
87

    
88

    
89
/* *************** VARIABLES *******************************/
90
    private Connection mConn;
91
    private Statement mStmt;
92
    private String mQuery;
93
    private String mUrl = null;
94
    private String mDb = null;
95
    private int mPort = 1433; //default port TODO 2 currently only for SQLServer, needs to be implemented also for othe DBMS
96
    private String mDbms = null;
97
    private String mServer = null;
98
    private boolean isCursor;
99
    private boolean connExist = false; //does a Connection exist?
100
    private String mUserName;
101
    private String mPwd;
102

    
103
	private boolean doLog = false;
104

    
105

    
106
	private static String userNameDefault = "sa"; //default user
107
    private static String pwdDefault = "sa"; //default PWD
108

    
109

    
110
/* ******************** CONSTRUCTORS **********************************/
111

    
112

    
113
    /**
114
     * Creates a source and sets the according variables
115
     * @param dbms name of database management system (e.g. "SQLServer", "Access", "Excel", "Oracle"
116
	 * @param server name of server, if dbms is ODBC, this must be the ODBC name
117
	 * @param db name of database
118
	*/
119
    public Source(String dbms, String server, String db){
120
    	mDbms = dbms;
121
        mServer = server;
122
        mDb = db;
123
        this.mPwd = pwdDefault;
124
        this.mUserName = userNameDefault;
125
    }
126

    
127
    /**
128
     * Creates a source and sets the query string
129
     * @param dbms name of database management system (e.g. "SQLServer", "Access", "Excel", "Oracle"
130
	 * @param server name of server, if dbms is ODBC, this must be the ODBC name
131
	 * @param db name of database
132
     * @param query the query
133
     */
134
    public Source(String dbms, String server, String db, String query){
135
        this(dbms, server, db);
136
        this.setQuery(query);
137
    }
138

    
139
    /**
140
    * Creates a source and sets the parameter.
141
     * @param cursor access mode, if true 'cursor', if false 'direct'
142
    */
143
    public Source(String dbms, String server, String db, boolean cursor)   {
144
        this(dbms, server, db);
145
    	isCursor = cursor;
146
    }
147

    
148

    
149
    /**
150
    * Creates a source and sets the parameter. If port is -1 the databases default port is used.
151
    * @param dbms name of database management system (e.g. "SQLServer", "Access", "Excel", "Oracle"
152
    * @param server name of server, if dbms is ODBC, this must be the ODBC name
153
    * @param db name of database
154
    * @param port the databases port (-1: use default port)
155
    */
156
    public Source(String dbms, String server, String db, int port) {
157
        this(dbms, server, db);
158
        if (port != -1){
159
        	this.setPort(port);
160
        };
161
    }
162

    
163
    /**
164
     * Creates a source with parameters of a ICdmDataSource instance
165
     *
166
     * @param cdmDataSource
167
     */
168
    public Source(ICdmDataSource cdmDataSource){
169
    	mDbms = cdmDataSource.getDatabaseType().getName();
170
        mServer = cdmDataSource.getServer();
171
        mDb = cdmDataSource.getDatabase();
172
        mPwd = cdmDataSource.getPassword();
173
        mUserName = cdmDataSource.getUsername();
174
        this.setPort(cdmDataSource.getPort());
175
    }
176

    
177
//********************* METHODS *****************************************************/
178

    
179
    //******* RESULTSETS *******************//
180
    /**
181
     * Returns the Resultset for query 'query'.
182
     * Does not change the Sources query-string!!
183
     * @return Resultset for the query.
184
     */
185
    public ResultSet getResultSet (String query){
186
    	ResultSet rs;
187
    	try {
188
            this.getConnection(); //establish connection
189
        	if (query == null){
190
        		return null;
191
        	}
192
            mStmt = mConn.createStatement();
193
            rs = mStmt.executeQuery(query);
194
            return rs;
195
        }catch(Exception e){
196
            logger.error("Problems when creating Resultset for query \n  " + query + " \n" + "Exception: " + e);
197
            throw new RuntimeException(e);
198
        }
199
    }
200

    
201
    public Object getUniqueResult (String query){
202
        ResultSet rs = getResultSet(query);
203
        try {
204
            if (!rs.next()){
205
                throw new IllegalStateException("No result for unique result query: " + query);
206
            }
207
            Object result = rs.getObject(1);
208
            return result;
209
        } catch (SQLException e) {
210
            throw new RuntimeException(e);
211
        }
212
    }
213

    
214
    public int getUniqueInteger (String query){
215
        Object result = getUniqueResult(query);
216
        if (result instanceof Long){
217
            Long theLong = (Long)result;
218
            result = Math.toIntExact(theLong);
219
        }
220
        return (Integer)result;
221
    }
222

    
223
    //******* INSERT, UPDATE, DELETE *******************//
224
    /**
225
     * Executes an insert, update or delete statement.
226
     * Returns the number of rows changed or -1 if updatedStatement was 0 or and error occurred.
227
     * Does not change the Sources query-string!!
228
     * @return Resultset for the query.
229
     */
230
    public int update (String updateStatement){
231
    	int result;
232
    	try {
233
            this.getConnection(); //establish connection
234
        	if (updateStatement == null){
235
        		return -1;
236
        	}
237
            mStmt = mConn.createStatement();
238
            result = mStmt.executeUpdate(updateStatement);
239
            return result;
240
        }catch(SQLException e){
241
            logger.error("Problems when creating Resultset for query \n  " + updateStatement + " \n" + "Exception: " + e);
242
            return -1;
243
        }
244
    }
245

    
246

    
247
    /**
248
     * Returns the Resultset for Sources query.
249
     * @return Resultset for the Sources query
250
     */
251
    public ResultSet getResultSet (){
252
    	return getResultSet(mQuery);
253
    }
254

    
255

    
256
    // ***************CONNECTION *************************************//
257
    /**
258
     * Returns the connection.
259
     * @return the Sources connection
260
     */
261
    public Connection getConnection(){
262
    	try {
263
			if (this.connExist == false){
264
				if (mConn != null){
265
					mConn.close();
266
				}
267
				this.makeConnection() ;
268
    		}
269
			return this.mConn;
270
		} catch (SourceConnectionException e) {
271
			throw new RuntimeException("Error when establishing Connection.", e);
272
		} catch (SQLException e) {
273
			throw new RuntimeException("SQLException in getConnection.", e);
274
		}
275
    }
276

    
277

    
278
    /**
279
     * Makes the connection.
280
     * @return true if connection created
281
     * @throws SourceConnectionException
282
     */
283
    private boolean makeConnection()throws SourceConnectionException {
284
    	if (doLog ){
285
    		DriverManager.setLogWriter(new PrintWriter(System.out));
286
    	}
287
    	try {
288
			if (makeConnectionString() == false){
289
				throw new SourceConnectionException ("Error in Connection String");
290
			}
291
			if (mDbms.equalsIgnoreCase(ODDBC) ){
292
				//not necessarily limited to ODBC
293
				java.util.Properties prop = new java.util.Properties();
294
//			    prop.put("charSet", "Big5");
295
			    prop.put("user", mUserName);
296
			    prop.put("password", mPwd);
297
//			    DriverManager.setLogWriter(new PrintWriter(System.out));
298
			    mConn = DriverManager.getConnection(mUrl, prop);
299
			}else{
300
				mConn = DriverManager.getConnection(mUrl, mUserName, mPwd);
301
			}
302

    
303

    
304

    
305
			mConn.setCatalog(mDb);  //
306
			logger.info("Connected to " + mConn.getCatalog());
307
			mStmt = mConn.createStatement();
308
			this.connExist = true;
309
			return true;
310
		}catch (SQLException e){
311
            logger.error("Problems when trying to open the database !!!\n" +
312
                    "URL: " + mUrl  + "\n" +
313
                    "Exception: " + e);
314
            throw new SourceConnectionException ();
315
        }
316
    }
317

    
318
    /**
319
     * Makes the connection string
320
     * @return false if ClassNotFoundException, else true
321
     */
322
    private boolean makeConnectionString(){
323
    	String selectMethod;
324
        String server;
325

    
326
    	if (isCursor) {
327
            selectMethod = SELECT_CURSOR;
328
        } else {
329
            selectMethod = SELECT_DIRECT;
330
        }
331
	    try{
332
	        if (DEBUG_LOG_WRITER) {
333
                DriverManager.setLogWriter((new PrintWriter(System.out)));
334
            } else if (mDbms.equalsIgnoreCase(SQL_SERVER_2005)) {
335
	            Class.forName(clsSQLServer2005);
336
	            server = mServer + ":" + mPort;
337
	            mUrl = urlSQLServer2005 + server + ";databaseName=" + mDb +";SelectMethod="+ selectMethod;
338
	        }
339
	        else if (mDbms.equalsIgnoreCase(SQL_SERVER_2008)) {
340
	            Class.forName(clsSQLServer2008);
341
	            server = mServer + ":" + mPort;
342
	            mUrl = urlSQLServer2008 + server + ";databaseName=" + mDb +";SelectMethod="+ selectMethod;
343
	        }
344
	        else if (mDbms.equalsIgnoreCase(ACCESS)) {
345
	        	Class.forName(clsODBC);
346

    
347
	        	//mDb must be the file path
348
	        	mUrl = urlODBC + "Driver={Microsoft Access Driver (*.mdb)};DBQ=";
349
	        	mUrl += mDb.trim() + ";DriverID=22;READONLY=false}";
350
	        }
351
	        else if (mDbms.equalsIgnoreCase(EXCEL)) {
352
	            Class.forName(clsODBC);
353
	            mUrl = urlODBC + "jdbc:odbc:Driver={Microsoft Excel Driver (*.xls)};DBQ=";
354
	            mUrl += mDb.trim() + ";DriverID=22;READONLY=false";
355
	        }
356
	        else if (mDbms.equalsIgnoreCase(ODDBC)) {
357
	            //mDb must be the System DNS name
358
	        	Class.forName(clsODBC);
359
	            mUrl = urlODBC + mDb ;
360
	        }
361
	        else if (mDbms.equalsIgnoreCase(ORACLE)) {
362
	            Class.forName(clsOracle);
363
	            mUrl = urlOracle + mDb ;
364
	        }
365
	        else if (mDbms.equalsIgnoreCase(DB2)) {
366
	            Class.forName(clsDB2);
367
	            mUrl = urlDB2 + mDb;
368
	        }
369
	        else if (mDbms.equalsIgnoreCase("SQLServerDdtek")) {
370
	             Class.forName(clsSQLServerDdtek);
371
	             mUrl = urlDataDirectSQLServer + mServer;
372
	        }
373
	        else if (mDbms.equalsIgnoreCase(POSTGRESQL9)) {
374
	            Class.forName(clsPostgreSQL);
375
	            server = mServer + ":" + mPort;
376
	            mUrl = urlPostgreSQL + server+ "/" + mDb;
377
	        }
378
	        else if (mDbms.equalsIgnoreCase(MYSQL)) {
379
                Class.forName(clsMySQL);
380
                server = mServer + ":" + mPort;
381
                mUrl = urlMySQL + server+ "/" + mDb + "?useUnicode=true&characterEncoding=utf8" + "&zeroDateTimeBehavior=convertToNull";
382
            }
383
	        else {
384
	            throw new RuntimeException("Unsupported Database type");
385
	        }
386
	        logger.debug("Connection String: " + mUrl);
387
	        return true;
388
	    }catch (ClassNotFoundException e){
389
	        logger.error("Datenbank-Treiber-Klasse konnte nicht geladen werden\n" + "Exception: " + e.toString());
390
	        return false;
391
	    }
392
    }
393

    
394

    
395
/* ******************** SETTER *************************************/
396

    
397
    /**
398
     * @param query
399
     */
400
    public Source setQuery (String query){
401
        mQuery = query;
402
        return this;
403
    }
404

    
405
    /**
406
     * Sets the username.
407
     * @param userName
408
     */
409
    public Source setUsername (String userName){
410
    	if (userName == null){
411
    		this.mUserName = userNameDefault;
412
    	}else{
413
    		this.mUserName = userName;
414
    	}
415
    	this.connExist = false;
416
		return this;
417
    }
418

    
419
    /**
420
     * Sets the password.
421
     * @param pwd
422
     */
423
    public Source setPassword (String pwd){
424
    	if (pwd == null){
425
    		this.mPwd = pwdDefault;
426
    	}else{
427
    		this.mPwd = pwd;
428
    	}
429
    	this.connExist = false;
430
		return this;
431
	}
432

    
433
    /**
434
     * Sets the username and password.
435
     * @param userName
436
     * @param pwd
437
     */
438
    public Source setUserAndPwd (String userName, String pwd){
439
    	setUsername(userName);
440
    	setPassword(pwd);
441
    	return this;
442
	}
443

    
444
    /**
445
     * Sets the port.
446
     * @param userName
447
     * @param pwd
448
     */
449
    public Source setPort (int port){
450
    	this.mPort = port;
451
		this.connExist = false;
452
		return this;
453
	}
454

    
455
    public String getDatabase(){
456
    	return mDb;
457
    }
458

    
459
    public String getServer(){
460
    	return mServer;
461
    }
462

    
463

    
464
    public boolean isDoLog() {
465
		return doLog;
466
	}
467

    
468
	public void setDoLog(boolean doLog) {
469
		this.doLog = doLog;
470
	}
471

    
472
    /**
473
     * Checks if an attribute exists in the database schema. At the moment only supported
474
     * for SQL Server.
475
     * TODO implement for others.
476
     * @param tableName
477
     * @param dbAttribute
478
     * @return
479
     * @throws MethodNotSupportedException
480
     */
481
    public boolean checkColumnExists(String tableName, String dbAttribute) throws DatabaseTypeNotSupportedException{
482
    	if (mDbms.equalsIgnoreCase(SQL_SERVER_2005)|| mDbms.equalsIgnoreCase(SQL_SERVER_2008) ){
483
    		String strQuery = "SELECT  Count(t.id) as n " +
484
				" FROM sysobjects AS t " +
485
				" INNER JOIN syscolumns AS c ON t.id = c.id " +
486
				" WHERE (t.xtype = 'U') AND " +
487
				" (t.name = '" + tableName + "') AND " +
488
				" (c.name = '" + dbAttribute + "')";
489
			ResultSet rs = getResultSet(strQuery) ;
490
			int n;
491
			try {
492
				rs.next();
493
				n = rs.getInt("n");
494
				return n>0;
495
			} catch (SQLException e) {
496
				e.printStackTrace();
497
				return false;
498
			}
499
    	}else{
500
    		throw new DatabaseTypeNotSupportedException("Check column exist is not supported by the database system");
501
    	}
502
    }
503

    
504
    @Override
505
    public String toString(){
506
    	if (mDb != null){
507
    		return mDb;
508
    	}else if (mUrl == null){
509
    		return super.toString();
510
    	}else{
511
        	return mUrl;
512
    	}
513
    }
514

    
515
}
(55-55/65)