KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mckoi > database > jdbcserver > JDBCDatabaseInterface


1 /**
2  * com.mckoi.database.jdbcserver.JDBCDatabaseInterface 16 Aug 2000
3  *
4  * Mckoi SQL Database ( http://www.mckoi.com/database )
5  * Copyright (C) 2000, 2001, 2002 Diehl and Associates, Inc.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * Version 2 as published by the Free Software Foundation.
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 Version 2 for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * Version 2 along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  *
20  * Change Log:
21  *
22  *
23  */

24
25 package com.mckoi.database.jdbcserver;
26
27 import com.mckoi.database.*;
28 import com.mckoi.database.jdbc.*;
29 import com.mckoi.util.StringUtil;
30 import com.mckoi.debug.*;
31
32 import java.sql.SQLException JavaDoc;
33
34 /**
35  * An implementation of jdbc.DatabaseInterface on the server-side.
36  * <p>
37  * This receives database commands and dispatches them to the database
38  * system. This assumes that all calls to the methods here are in a
39  * UserWorkerThread thread.
40  * <p>
41  * NOTE: Currently, the client/server use of this object isn't multi-threaded,
42  * however the local connection could be. Therefore, this object has been
43  * made multi-thread safe.
44  *
45  * @author Tobias Downer
46  */

47
48 public class JDBCDatabaseInterface extends AbstractJDBCDatabaseInterface {
49
50   /**
51    * Set this to true if command logging is enabled.
52    */

53   private static final boolean COMMAND_LOGGING = true;
54
55   /**
56    * The unique host name denoting the client that's connected.
57    */

58   private String JavaDoc host_name;
59
60   /**
61    * Sets up the processor.
62    */

63   public JDBCDatabaseInterface(Database database, String JavaDoc host_name) {
64     super(database);
65     this.host_name = host_name;
66   }
67
68   /**
69    * Tries to authenticate the username and password against the given
70    * database. Returns true if we are successful. If successful, alters the
71    * state of this object to reflect the fact the user has logged in.
72    */

73   private boolean authenticate(Database database, String JavaDoc default_schema,
74                                String JavaDoc username, String JavaDoc password,
75                                final DatabaseCallBack database_call_back) {
76
77     // If the 'user' variable is null, no one is currently logged in to this
78
// connection.
79

80     if (getUser() == null) {
81
82       if (COMMAND_LOGGING && database.getSystem().logQueries()) {
83         // Output the instruction to the commands log.
84
StringBuffer JavaDoc log_str = new StringBuffer JavaDoc();
85         log_str.append("[JDBC] [");
86         log_str.append(username);
87         log_str.append("] ");
88         log_str.append('[');
89         log_str.append(host_name);
90         log_str.append("] ");
91         log_str.append("Log in.\n");
92         database.getCommandsLog().log(new String JavaDoc(log_str));
93       }
94
95       // Write debug message,
96
if (Debug().isInterestedIn(Lvl.INFORMATION)) {
97         Debug().write(Lvl.INFORMATION, this,
98                     "Authenticate User: " + username);
99       }
100
101       // Create a UserCallBack class.
102
DatabaseConnection.CallBack call_back =
103                                            new DatabaseConnection.CallBack() {
104         public void triggerNotify(String JavaDoc trigger_name, int trigger_event,
105                                   String JavaDoc trigger_source, int fire_count) {
106           StringBuffer JavaDoc message = new StringBuffer JavaDoc();
107           message.append(trigger_name);
108           message.append(' ');
109           message.append(trigger_source);
110           message.append(' ');
111           message.append(fire_count);
112
113           database_call_back.databaseEvent(99, new String JavaDoc(message));
114         }
115       };
116
117       // Try to create a User object.
118
User this_user = database.authenticateUser(username, password,
119                                                  host_name);
120       DatabaseConnection database_connection = null;
121
122       // If successful, ask the engine for a DatabaseConnection object.
123
if (this_user != null) {
124         database_connection =
125                            database.createNewConnection(this_user, call_back);
126
127         // Put the connection in exclusive mode
128
LockingMechanism locker = database_connection.getLockingMechanism();
129         locker.setMode(LockingMechanism.EXCLUSIVE_MODE);
130         try {
131
132           // By default, JDBC connections are auto-commit
133
database_connection.setAutoCommit(true);
134
135           // Set the default schema for this connection if it exists
136
if (database_connection.schemaExists(default_schema)) {
137             database_connection.setDefaultSchema(default_schema);
138           }
139           else {
140             Debug().write(Lvl.WARNING, this,
141                       "Couldn't change to '" + default_schema + "' schema.");
142             // If we can't change to the schema then change to the APP schema
143
database_connection.setDefaultSchema("APP");
144           }
145
146         }
147         finally {
148           try {
149             // Make sure we commit the connection.
150
database_connection.commit();
151           }
152           catch (TransactionException e) {
153             // Just issue a warning...
154
Debug().writeException(Lvl.WARNING, e);
155           }
156           finally {
157             // Guarentee that we unluck from EXCLUSIVE
158
locker.finishMode(LockingMechanism.EXCLUSIVE_MODE);
159           }
160         }
161
162       }
163
164       // If we have a user object, then init the object,
165
if (this_user != null) {
166         init(this_user, database_connection);
167         return true;
168       }
169       else {
170         // Otherwise, return false.
171
return false;
172       }
173
174     }
175     else {
176       throw new RuntimeException JavaDoc("Attempt to authenticate user twice");
177     }
178
179   }
180
181   // ---------- Implemented from DatabaseInterface ----------
182

183   public boolean login(String JavaDoc default_schema, String JavaDoc username, String JavaDoc password,
184                        DatabaseCallBack database_call_back)
185                                                         throws SQLException JavaDoc {
186
187     Database database = getDatabase();
188
189     boolean b = authenticate(database, default_schema, username, password,
190                              database_call_back);
191     return b;
192   }
193
194
195
196
197
198   public QueryResponse execQuery(SQLQuery query) throws SQLException JavaDoc {
199
200     // Check the interface isn't disposed (connection was closed).
201
checkNotDisposed();
202     
203     User user = getUser();
204     DatabaseConnection database_connection = getDatabaseConnection();
205
206     // Log this query if query logging is enabled
207
if (COMMAND_LOGGING && getDatabase().getSystem().logQueries()) {
208       // Output the instruction to the commands log.
209
StringBuffer JavaDoc log_str = new StringBuffer JavaDoc();
210       log_str.append("[JDBC] [");
211       log_str.append(user.getUserName());
212       log_str.append("] ");
213       log_str.append('[');
214       log_str.append(host_name);
215       log_str.append("] ");
216       log_str.append("Query: ");
217       log_str.append(query.getQuery());
218       log_str.append('\n');
219       user.getDatabase().getCommandsLog().log(new String JavaDoc(log_str));
220     }
221
222     // Write debug message (INFORMATION level)
223
if (Debug().isInterestedIn(Lvl.INFORMATION)) {
224       Debug().write(Lvl.INFORMATION, this,
225                     "Query From User: " + user.getUserName() + "@" + host_name);
226       Debug().write(Lvl.INFORMATION, this,
227                     "Query: " + query.getQuery().trim());
228     }
229
230     // Get the locking mechanism.
231
LockingMechanism locker = database_connection.getLockingMechanism();
232     int lock_mode = -1;
233     QueryResponse response = null;
234     try {
235       try {
236
237         // For simplicity - all database locking is now exclusive inside
238
// a transaction. This means it is not possible to execute
239
// queries concurrently inside a transaction. However, we are
240
// still able to execute queries concurrently from different
241
// connections.
242
//
243
// It's debatable whether we even need to perform this lock anymore
244
// because we could change the contract of this method so that
245
// it is not thread safe. This would require that the callee ensures
246
// more than one thread can not execute queries on the connection.
247
lock_mode = LockingMechanism.EXCLUSIVE_MODE;
248         locker.setMode(lock_mode);
249
250         // Execute the query (behaviour for this comes from super).
251
response = super.execQuery(query);
252
253         // Return the result.
254
return response;
255
256       }
257       finally {
258         try {
259           // This is executed no matter what happens. Very important we
260
// unlock the tables.
261
if (lock_mode != -1) {
262             locker.finishMode(lock_mode);
263           }
264         }
265         catch (Throwable JavaDoc e) {
266           // If this throws an exception, we should output it to the debug
267
// log and screen.
268
e.printStackTrace(System.err);
269           Debug().write(Lvl.ERROR, this, "Exception finishing locks");
270           Debug().writeException(e);
271           // Note, we can't throw an error here because we may already be in
272
// an exception that happened in the above 'try' block.
273
}
274       }
275
276     }
277     finally {
278       // This always happens after tables are unlocked.
279
// Also guarenteed to happen even if something fails.
280

281       // If we are in auto-commit mode then commit the query here.
282
// Do we auto-commit?
283
if (database_connection.getAutoCommit()) {
284         // Yes, so grab an exclusive lock and auto-commit.
285
try {
286           // Lock into exclusive mode.
287
locker.setMode(LockingMechanism.EXCLUSIVE_MODE);
288           // If an error occured then roll-back
289
if (response == null) {
290             // Rollback.
291
database_connection.rollback();
292           }
293           else {
294             try {
295               // Otherwise commit.
296
database_connection.commit();
297             }
298             catch (Throwable JavaDoc e) {
299               // Dispose this response if the commit failed.
300
disposeResult(response.getResultID());
301               // And throw the SQL Exception
302
throw handleExecuteThrowable(e, query);
303             }
304           }
305         }
306         finally {
307           locker.finishMode(LockingMechanism.EXCLUSIVE_MODE);
308         }
309       }
310
311     }
312
313   }
314
315
316   public void dispose() throws SQLException JavaDoc {
317     if (getUser() != null) {
318       DatabaseConnection database = getDatabaseConnection();
319       LockingMechanism locker = database.getLockingMechanism();
320       try {
321         // Lock into exclusive mode,
322
locker.setMode(LockingMechanism.EXCLUSIVE_MODE);
323         // Roll back any open transaction.
324
database.rollback();
325       }
326       finally {
327         // Finish being in exclusive mode.
328
locker.finishMode(LockingMechanism.EXCLUSIVE_MODE);
329         // Close the database connection object.
330
database.close();
331         // Log out the user
332
getUser().logout();
333         // Call the internal dispose method.
334
internalDispose();
335       }
336     }
337   }
338
339 }
340
Popular Tags