Project

General

Profile

Download (15.3 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.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 = Logger.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
    //******* INSERT, UPDATE, DELETE *******************//
202
    /**
203
     * Executes an insert, update or delete statement.
204
     * Returns the number of rows changed or -1 if updatedStatement was 0 or and error occurred.
205
     * Does not change the Sources query-string!!
206
     * @return Resultset for the query.
207
     */
208
    public int update (String updateStatement){
209
    	int result;
210
    	try {
211
            this.getConnection(); //establish connection
212
        	if (updateStatement == null){
213
        		return -1;
214
        	}
215
            mStmt = mConn.createStatement();
216
            result = mStmt.executeUpdate(updateStatement);
217
            return result;
218
        }catch(SQLException e){
219
            logger.error("Problems when creating Resultset for query \n  " + updateStatement + " \n" + "Exception: " + e);
220
            return -1;
221
        }
222
    }
223

    
224

    
225
    /**
226
     * Returns the Resultset for Sources query.
227
     * @return Resultset for the Sources query
228
     */
229
    public ResultSet getResultSet (){
230
    	return getResultSet(mQuery);
231
    }
232

    
233

    
234
    // ***************CONNECTION *************************************//
235
    /**
236
     * Returns the connection.
237
     * @return the Sources connection
238
     */
239
    public Connection getConnection(){
240
    	try {
241
			if (this.connExist == false){
242
				if (mConn != null){
243
					mConn.close();
244
				}
245
				this.makeConnection() ;
246
    		}
247
			return this.mConn;
248
		} catch (SourceConnectionException e) {
249
			throw new RuntimeException("Error when establishing Connection.", e);
250
		} catch (SQLException e) {
251
			throw new RuntimeException("SQLException in getConnection.", e);
252
		}
253
    }
254

    
255

    
256
    /**
257
     * Makes the connection.
258
     * @return true if connection created
259
     * @throws SourceConnectionException
260
     */
261
    private boolean makeConnection()throws SourceConnectionException {
262
    	if (doLog ){
263
    		DriverManager.setLogWriter(new PrintWriter(System.out));
264
    	}
265
    	try {
266
			if (makeConnectionString() == false){
267
				throw new SourceConnectionException ("Error in Connection String");
268
			}
269
			if (mDbms.equalsIgnoreCase(ODDBC) ){
270
				//not necessarily limited to ODBC
271
				java.util.Properties prop = new java.util.Properties();
272
//			    prop.put("charSet", "Big5");
273
			    prop.put("user", mUserName);
274
			    prop.put("password", mPwd);
275
//			    DriverManager.setLogWriter(new PrintWriter(System.out));
276
			    mConn = DriverManager.getConnection(mUrl, prop);
277
			}else{
278
				mConn = DriverManager.getConnection(mUrl, mUserName, mPwd);
279
			}
280

    
281

    
282

    
283
			mConn.setCatalog(mDb);  //
284
			logger.info("Connected to " + mConn.getCatalog());
285
			mStmt = mConn.createStatement();
286
			this.connExist = true;
287
			return true;
288
		}catch (SQLException e){
289
            logger.error("Problems when trying to open the database !!!\n" +
290
                    "URL: " + mUrl  + "\n" +
291
                    "Exception: " + e);
292
            throw new SourceConnectionException ();
293
        }
294
    }
295

    
296
    /**
297
     * Makes the connection string
298
     * @return false if ClassNotFoundException, else true
299
     */
300
    private boolean makeConnectionString(){
301
    	String selectMethod;
302
        String server;
303

    
304
    	if (isCursor) {
305
            selectMethod = SELECT_CURSOR;
306
        } else {
307
            selectMethod = SELECT_DIRECT;
308
        }
309
	    try{
310
	        if (DEBUG_LOG_WRITER) {
311
                DriverManager.setLogWriter((new PrintWriter(System.out)));
312
            } else if (mDbms.equalsIgnoreCase(SQL_SERVER_2005)) {
313
	            Class.forName(clsSQLServer2005);
314
	            server = mServer + ":" + mPort;
315
	            mUrl = urlSQLServer2005 + server + ";databaseName=" + mDb +";SelectMethod="+ selectMethod;
316
	        }
317
	        else if (mDbms.equalsIgnoreCase(SQL_SERVER_2008)) {
318
	            Class.forName(clsSQLServer2008);
319
	            server = mServer + ":" + mPort;
320
	            mUrl = urlSQLServer2008 + server + ";databaseName=" + mDb +";SelectMethod="+ selectMethod;
321
	        }
322
	        else if (mDbms.equalsIgnoreCase(ACCESS)) {
323
	        	Class.forName(clsODBC);
324

    
325
	        	//mDb must be the file path
326
	        	mUrl = urlODBC + "Driver={Microsoft Access Driver (*.mdb)};DBQ=";
327
	        	mUrl += mDb.trim() + ";DriverID=22;READONLY=false}";
328
	        }
329
	        else if (mDbms.equalsIgnoreCase(EXCEL)) {
330
	            Class.forName(clsODBC);
331
	            mUrl = urlODBC + "jdbc:odbc:Driver={Microsoft Excel Driver (*.xls)};DBQ=";
332
	            mUrl += mDb.trim() + ";DriverID=22;READONLY=false";
333
	        }
334
	        else if (mDbms.equalsIgnoreCase(ODDBC)) {
335
	            //mDb must be the System DNS name
336
	        	Class.forName(clsODBC);
337
	            mUrl = urlODBC + mDb ;
338
	        }
339
	        else if (mDbms.equalsIgnoreCase(ORACLE)) {
340
	            Class.forName(clsOracle);
341
	            mUrl = urlOracle + mDb ;
342
	        }
343
	        else if (mDbms.equalsIgnoreCase(DB2)) {
344
	            Class.forName(clsDB2);
345
	            mUrl = urlDB2 + mDb;
346
	        }
347
	        else if (mDbms.equalsIgnoreCase("SQLServerDdtek")) {
348
	             Class.forName(clsSQLServerDdtek);
349
	             mUrl = urlDataDirectSQLServer + mServer;
350
	        }
351
	        else if (mDbms.equalsIgnoreCase(POSTGRESQL9)) {
352
	            Class.forName(clsPostgreSQL);
353
	            server = mServer + ":" + mPort;
354
	            mUrl = urlPostgreSQL + server+ "/" + mDb;
355
	        }
356
	        else if (mDbms.equalsIgnoreCase(MYSQL)) {
357
                Class.forName(clsMySQL);
358
                server = mServer + ":" + mPort;
359
                mUrl = urlMySQL + server+ "/" + mDb + "?useUnicode=true&characterEncoding=utf8" + "&zeroDateTimeBehavior=convertToNull";
360
            }
361
	        else {
362
	            throw new RuntimeException("Unsupported Database type");
363
	        }
364
	        logger.debug("Connection String: " + mUrl);
365
	        return true;
366
	    }catch (ClassNotFoundException e){
367
	        logger.error("Datenbank-Treiber-Klasse konnte nicht geladen werden\n" + "Exception: " + e.toString());
368
	        return false;
369
	    }
370
    }
371

    
372

    
373
/* ******************** SETTER *************************************/
374

    
375
    /**
376
     * @param query
377
     */
378
    public Source setQuery (String query){
379
        mQuery = query;
380
        return this;
381
    }
382

    
383
    /**
384
     * Sets the username.
385
     * @param userName
386
     */
387
    public Source setUsername (String userName){
388
    	if (userName == null){
389
    		this.mUserName = userNameDefault;
390
    	}else{
391
    		this.mUserName = userName;
392
    	}
393
    	this.connExist = false;
394
		return this;
395
    }
396

    
397
    /**
398
     * Sets the password.
399
     * @param pwd
400
     */
401
    public Source setPassword (String pwd){
402
    	if (pwd == null){
403
    		this.mPwd = pwdDefault;
404
    	}else{
405
    		this.mPwd = pwd;
406
    	}
407
    	this.connExist = false;
408
		return this;
409
	}
410

    
411
    /**
412
     * Sets the username and password.
413
     * @param userName
414
     * @param pwd
415
     */
416
    public Source setUserAndPwd (String userName, String pwd){
417
    	setUsername(userName);
418
    	setPassword(pwd);
419
    	return this;
420
	}
421

    
422
    /**
423
     * Sets the port.
424
     * @param userName
425
     * @param pwd
426
     */
427
    public Source setPort (int port){
428
    	this.mPort = port;
429
		this.connExist = false;
430
		return this;
431
	}
432

    
433
    public String getDatabase(){
434
    	return mDb;
435
    }
436

    
437
    public String getServer(){
438
    	return mServer;
439
    }
440

    
441

    
442
    public boolean isDoLog() {
443
		return doLog;
444
	}
445

    
446
	public void setDoLog(boolean doLog) {
447
		this.doLog = doLog;
448
	}
449

    
450
    /**
451
     * Checks if an attribute exists in the database schema. At the moment only supported
452
     * for SQL Server.
453
     * TODO implement for others.
454
     * @param tableName
455
     * @param dbAttribute
456
     * @return
457
     * @throws MethodNotSupportedException
458
     */
459
    public boolean checkColumnExists(String tableName, String dbAttribute) throws DatabaseTypeNotSupportedException{
460
    	if (mDbms.equalsIgnoreCase(SQL_SERVER_2005)|| mDbms.equalsIgnoreCase(SQL_SERVER_2008) ){
461
    		String strQuery = "SELECT  Count(t.id) as n " +
462
				" FROM sysobjects AS t " +
463
				" INNER JOIN syscolumns AS c ON t.id = c.id " +
464
				" WHERE (t.xtype = 'U') AND " +
465
				" (t.name = '" + tableName + "') AND " +
466
				" (c.name = '" + dbAttribute + "')";
467
			ResultSet rs = getResultSet(strQuery) ;
468
			int n;
469
			try {
470
				rs.next();
471
				n = rs.getInt("n");
472
				return n>0;
473
			} catch (SQLException e) {
474
				e.printStackTrace();
475
				return false;
476
			}
477
    	}else{
478
    		throw new DatabaseTypeNotSupportedException("Check column exist is not supported by the database system");
479
    	}
480
    }
481

    
482
    @Override
483
    public String toString(){
484
    	if (mDb != null){
485
    		return mDb;
486
    	}else if (mUrl == null){
487
    		return super.toString();
488
    	}else{
489
        	return mUrl;
490
    	}
491
    }
492

    
493
}
(54-54/63)