001 /*
002 * DBHelper.java
003 *
004 * Copyright (c) 1995-2010, The University of Sheffield. See the file
005 * COPYRIGHT.txt in the software or at http://gate.ac.uk/gate/COPYRIGHT.txt
006 *
007 * This file is part of GATE (see http://gate.ac.uk/), and is free
008 * software, licenced under the GNU Library General Public License,
009 * Version 2, June 1991 (in the distribution as file licence.html,
010 * and also available at http://gate.ac.uk/gate/licence.html).
011 *
012 * Marin Dimitrov, 18/Sep/2001
013 *
014 * $Id: DBHelper.java 12006 2009-12-01 17:24:28Z thomas_heitz $
015 */
016
017 package gate.persist;
018
019 import java.sql.*;
020 import java.util.HashMap;
021
022 import gate.Gate;
023
024 public class DBHelper {
025
026 /** class name of the Oracle jdbc driver */
027 private static final String jdbcOracleDriverName
028 = "oracle.jdbc.driver.OracleDriver";
029 private static final String jdbcPostgresDriverName
030 = "org.postgresql.Driver";
031
032 public static final int CHINK_SIZE_SMALL = 30;
033 public static final int CHINK_SIZE_MEDIUM = 60;
034 public static final int CHINK_SIZE_LARGE = 100;
035
036 //WARNING!
037 //DO NOT EDIT THESE CONSTANTS WITHOUT
038 //SYNCHRONIZING WITH ERROR.SPC PL/SQL PACKAGE
039 //note that while Oracle returns negative error numbers
040 //the SQLException::getErrorCode() returns positive ones
041 //
042
043 /** user defined error codes in Oracle start with -21000 */
044 public static final int X_ORACLE_START = 20100;
045
046 /** this should be thrown if an attempt to create a group with duplicated name is made */
047 public static final int X_ORACLE_DUPLICATE_GROUP_NAME = X_ORACLE_START + 1 ;
048
049 /** see above */
050 public static final int X_ORACLE_DUPLICATE_USER_NAME = X_ORACLE_START + 2 ;
051
052 /** no such user failure upon login */
053 public static final int X_ORACLE_INVALID_USER_NAME = X_ORACLE_START + 3 ;
054
055 /** - */
056 public static final int X_ORACLE_INVALID_USER_PASS = X_ORACLE_START + 4 ;
057
058 /** invalid group id supplied for operation requiring such specifier */
059 public static final int X_ORACLE_INVALID_USER_GROUP = X_ORACLE_START + 5 ;
060
061 /** access to LR by id fails - no such resource */
062 public static final int X_ORACLE_INVALID_LR = X_ORACLE_START + 6 ;
063
064 /** attempt to access resource in mode that does not exist */
065 public static final int X_ORACLE_INVALID_ACCESS_MODE = X_ORACLE_START + 7 ;
066
067 /** huh? */
068 public static final int X_ORACLE_INVALID_ARGUMENT = X_ORACLE_START + 8 ;
069
070 /** this should not be in use anymore */
071 public static final int X_ORACLE_NOT_IMPLEMENTED = X_ORACLE_START + 9 ;
072
073 /** attempt to delete a group that owns resources is made */
074 public static final int X_ORACLE_GROUP_OWNS_RESOURCES = X_ORACLE_START + 10 ;
075
076 /** attempt to delete a user that owns resources is made */
077 public static final int X_ORACLE_USER_OWNS_RESOURCES = X_ORACLE_START + 11 ;
078
079 /** huh? */
080 public static final int X_ORACLE_INCOMPLETE_DATA = X_ORACLE_START + 12 ;
081
082 /** attempt to access resources by type is made, but no such type exists */
083 public static final int X_ORACLE_INVALID_LR_TYPE = X_ORACLE_START + 13 ;
084
085 /** this is obsolete now? */
086 public static final int X_ORACLE_INVALID_ANNOTATION_TYPE = X_ORACLE_START + 14 ;
087
088 /** attempt to create a feature with invalid value type is made
089 * since value types are automatically assigned in the java code, this errror
090 * should indicate that the java code was changed but no changes were made to the
091 * relevant pl/sql code
092 * */
093 public static final int X_ORACLE_INVALID_FEATURE_TYPE = X_ORACLE_START + 15 ;
094
095 /**
096 * not supported content type - we support only character/binary/empty content
097 * since there are no many other options this error shoudkl indicate that the
098 * java code was not synced with the pl/sql one
099 *
100 * */
101 public static final int X_ORACLE_INVALID_CONTENT_TYPE = X_ORACLE_START + 16 ;
102
103 /** attempt to remove annotation that does not exist is made */
104 public static final int X_ORACLE_INVALID_ANNOTATION = X_ORACLE_START + 17 ;
105
106 /** attempt to perform an operation that requres more privileged is made */
107 public static final int X_ORACLE_INSUFFICIENT_PRIVILEGES = X_ORACLE_START + 18 ;
108
109 /** attempt to remove annotation set that does not exist is made */
110 public static final int X_ORACLE_INVALID_ANNOTATION_SET = X_ORACLE_START + 19 ;
111
112 public static final int TRUE = 1;
113 public static final int FALSE = 0;
114
115 /** character content (may make difference for the database) */
116 public static final int CHARACTER_CONTENT = 1;
117
118 /** binary content (may make difference for the database) */
119 public static final int BINARY_CONTENT = 2;
120
121 /** document has no content*/
122 public static final int EMPTY_CONTENT = 3;
123
124 /** LR classes supported at present */
125 public static final String DOCUMENT_CLASS = "gate.corpora.DatabaseDocumentImpl";
126 /** LR classes supported at present */
127 public static final String CORPUS_CLASS = "gate.corpora.DatabaseCorpusImpl";
128
129 /** key in T_PARAMETER that defines a unique id for the data store */
130 public static final String DB_PARAMETER_GUID = "DB_GUID";
131
132 //dummy key
133 //hopefully no one will create a feature with such key
134 /** dummy feature key, do not use it */
135 public static final String DUMMY_FEATURE_KEY = "--NO--SUCH--KEY--";
136 /** dummy encoding type, do not use it */
137 public static final String DUMMY_ENCODING = "-!-";
138
139 /** used internaly, may change in the future */
140 public static final int READ_ACCESS = 0;
141 /** used internaly, may change in the future */
142 public static final int WRITE_ACCESS = 1;
143
144 //dummy ID
145 /** huh? */
146 public static final Long DUMMY_ID;
147
148
149 //!!! WARNING !!!
150 // these 4 constants should *always* be synchronzied with the ones in the
151 // related SQL packages/scripts [for Oracle - security.spc]
152 // i.e. if u don't have a serious reason do *not* change anything
153
154 /** used to store corpus' features */
155 protected static final int FEATURE_OWNER_CORPUS = 1;
156 /** used to store document's features */
157 protected static final int FEATURE_OWNER_DOCUMENT = 2;
158 /** used to store annotation's features */
159 protected static final int FEATURE_OWNER_ANNOTATION = 3;
160
161 /** feature value is null */
162 public static final int VALUE_TYPE_NULL = 100;
163 /** feature value is int */
164 public static final int VALUE_TYPE_INTEGER = 101;
165 /** feature value is long */
166 public static final int VALUE_TYPE_LONG = 102;
167 /** feature value is boolean */
168 public static final int VALUE_TYPE_BOOLEAN = 103;
169 /** feature value is string less than 4000 bytes */
170 public static final int VALUE_TYPE_STRING = 104;
171 /** feature value is binary */
172 public static final int VALUE_TYPE_BINARY = 105;
173 /** feature value is float */
174 public static final int VALUE_TYPE_FLOAT = 106;
175 /** feature value is array of ints */
176 public static final int VALUE_TYPE_INTEGER_ARR = 107;
177 /** feature value is array of longs */
178 public static final int VALUE_TYPE_LONG_ARR = 108;
179 /** feature value is array of bools */
180 public static final int VALUE_TYPE_BOOLEAN_ARR = 109;
181 /** feature value is array of strings */
182 public static final int VALUE_TYPE_STRING_ARR = 110;
183 /** feature value is array of binary values */
184 public static final int VALUE_TYPE_BINARY_ARR = 111;
185 /** feature value is array of floats */
186 public static final int VALUE_TYPE_FLOAT_ARR = 112;
187 /** feature value is array of floats */
188 public static final int VALUE_TYPE_EMPTY_ARR = 113;
189
190 /** Oracle database type */
191 public static final int ORACLE_DB = 101;
192 /** PostgreSQL database type */
193 public static final int POSTGRES_DB = 102;
194
195 private static final boolean DEBUG = false;
196
197 private static boolean oracleLoaded = false;
198 private static boolean postgresLoaded = false;
199 private static HashMap pools;
200
201 /** size (in elements) of the jdbc connection pool (if any) */
202 private static final int POOL_SIZE = 20;
203
204 static {
205 DUMMY_ID = new Long(Long.MIN_VALUE);
206 pools = new HashMap();
207 }
208
209
210 protected DBHelper() {
211
212 //no way
213 //contains only static methods
214 }
215
216 /** --- */
217 private static synchronized void loadDrivers(final int dbType)
218 throws ClassNotFoundException {
219
220 if (!oracleLoaded && dbType == ORACLE_DB) {
221 Class.forName(jdbcOracleDriverName);
222 } else if (!postgresLoaded && dbType == POSTGRES_DB) {
223 Class.forName(jdbcPostgresDriverName);
224 }
225 }
226
227
228 /**
229 * closes a result set
230 * note that Oracle jdbc classes do not have finalize() implementations so if
231 * they're not closed leaks may occur
232 */
233 public static void cleanup(ResultSet rs)
234 throws PersistenceException {
235
236 try {
237 if (rs!=null)
238 rs.close();
239 }
240 catch(SQLException sqle) {
241 throw new PersistenceException("an SQL exception occured ["+ sqle.getMessage()+"]");
242 }
243 }
244
245 /**
246 * closes a statement
247 * note that Oracle jdbc classes do not have finalize() implementations so if
248 * they're not closed leaks may occur
249 */
250 public static void cleanup(Statement stmt)
251 throws PersistenceException {
252 try {
253 if (stmt!=null)
254 stmt.close();
255 }
256 catch(SQLException sqle) {
257 throw new PersistenceException("an SQL exception occured ["+ sqle.getMessage()+"]");
258 }
259 }
260
261 /**
262 * connects to DB
263 */
264 public static Connection connect(final String connectURL)
265 throws SQLException,ClassNotFoundException{
266
267 loadDrivers( getDatabaseType(connectURL) );
268 Connection conn = DriverManager.getConnection(connectURL);
269
270 if (DEBUG) {
271 DatabaseMetaData meta = conn.getMetaData();
272 gate.util.Out.println(
273 "JDBC driver name=["+meta.getDriverName() +
274 "] version=["+ meta.getDriverVersion() +"]");
275 }
276
277 return conn;
278 }
279
280 /**
281 * connects to DB
282 */
283 public static Connection connect(final String connectURL,
284 final String user,
285 final String pass)
286 throws SQLException,ClassNotFoundException{
287
288 loadDrivers( getDatabaseType(connectURL) );
289 Connection conn = DriverManager.getConnection(connectURL, user, pass);
290
291 if (DEBUG) {
292 DatabaseMetaData meta = conn.getMetaData();
293 gate.util.Err.println(
294 "JDBC driver name=["+meta.getDriverName() +
295 "] version=["+ meta.getDriverVersion() +"]");
296 }
297
298 return conn;
299 }
300
301 /**
302 * disconnects from DB, may return connection to pool if such exists
303 *
304 * any uncommited transactions are rolled back
305 */
306 public static void disconnect(Connection conn)
307 throws PersistenceException{
308
309 //2. close the JDBC connection
310 try {
311 //rollback uncommited transactions
312 conn.rollback();
313 conn.close();
314 }
315 catch (SQLException sqle) {
316 throw new PersistenceException("cannot close JDBC connection, DB error is ["+
317 sqle.getMessage() +"]");
318 }
319 }
320
321 /**
322 * connects to DB
323 * gets connection from pool if such exists
324 */
325 public static Connection connect(String connectURL,boolean usePool)
326 throws SQLException,ClassNotFoundException{
327
328 if (false == usePool) {
329 return connect(connectURL);
330 }
331 else {
332 ConnectionPool currPool = null;
333
334 synchronized(pools) {
335 if (false == pools.containsKey(connectURL)) {
336 currPool = new ConnectionPool(POOL_SIZE, connectURL);
337 pools.put(connectURL, currPool);
338 }
339 else {
340 currPool = (ConnectionPool) pools.get(connectURL);
341 }
342 }
343
344 return currPool.get();
345 }
346 }
347
348 /**
349 * disconnects from DB, may return connection to pool if such exists
350 *
351 * any uncommited transactions are rolled back
352 */
353 public static void disconnect(Connection conn, boolean usePool)
354 throws PersistenceException{
355
356 if (false == usePool) {
357 disconnect(conn);
358 }
359 else {
360 String jdbcURL = null;
361
362 try {
363 jdbcURL = conn.getMetaData().getURL();
364 conn.rollback();
365 }
366 catch(SQLException sqle) {
367 throw new PersistenceException(sqle);
368 }
369
370 ConnectionPool currPool = (ConnectionPool) pools.get(jdbcURL);
371 currPool.put(conn);
372 }
373 }
374
375 public static String getSchemaPrefix(String jdbcURL) {
376
377 if (jdbcURL.startsWith("jdbc:oracle")) {
378 return Gate.DB_OWNER+".";
379 }
380 else if (jdbcURL.startsWith("jdbc:postgres")) {
381 return "";
382 }
383 else {
384 throw new IllegalArgumentException();
385 }
386 }
387
388 public static int getDatabaseType(String jdbcURL) {
389
390 if (jdbcURL.startsWith("jdbc:oracle")) {
391 return DBHelper.ORACLE_DB;
392 }
393 else if (jdbcURL.startsWith("jdbc:postgres")) {
394 return DBHelper.POSTGRES_DB;
395 }
396 else {
397 throw new IllegalArgumentException();
398 }
399 }
400
401 }
|