1 24 25 package com.mckoi.database.jdbcserver; 26 27 import com.mckoi.database.global.ObjectTransfer; 28 import com.mckoi.database.jdbc.StreamableObjectPart; 29 import com.mckoi.database.jdbc.ProtocolConstants; 30 import com.mckoi.database.jdbc.MSQLException; 31 import com.mckoi.database.jdbc.DatabaseCallBack; 32 import com.mckoi.database.jdbc.DatabaseInterface; 33 import com.mckoi.database.jdbc.QueryResponse; 34 import com.mckoi.database.jdbc.ResultPart; 35 import com.mckoi.database.jdbc.SQLQuery; 36 import com.mckoi.debug.*; 37 import com.mckoi.util.ByteArrayUtil; 38 39 import java.sql.SQLException ; 40 import java.io.*; 41 42 51 52 abstract class JDBCProcessor implements ProtocolConstants { 53 54 57 private static final int SERVER_VERSION = 1; 58 59 60 64 private int state; 65 66 69 private int authentication_tries; 70 71 74 private DatabaseInterface db_interface; 75 76 79 private DebugLogger debug; 80 81 84 JDBCProcessor(DatabaseInterface db_interface, DebugLogger logger) { 85 this.debug = logger; 86 this.db_interface = db_interface; 87 state = 0; 88 authentication_tries = 0; 89 } 90 91 95 private DatabaseCallBack db_call_back = new DatabaseCallBack() { 96 public void databaseEvent(int event_type, String event_message) { 97 try { 98 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 100 DataOutputStream dout = new DataOutputStream(bout); 101 dout.writeInt(event_type); 102 dout.writeUTF(event_message); 103 sendEvent(bout.toByteArray()); 104 } 105 catch (IOException e) { 106 debug.write(Lvl.ERROR, this, "IO Error: " + e.getMessage()); 107 debug.writeException(e); 108 } 109 } 110 }; 111 112 protected static void printByteArray(byte[] array) { 113 System.out.println("Length: " + array.length); 114 for (int i = 0; i < array.length; ++i) { 115 System.out.print(array[i]); 116 System.out.print(", "); 117 } 118 } 119 120 125 byte[] processJDBCCommand(byte[] command) throws IOException { 126 127 129 if (state == 0) { 130 int magic = ByteArrayUtil.getInt(command, 0); 132 int maj_ver = ByteArrayUtil.getInt(command, 4); 134 int min_ver = ByteArrayUtil.getInt(command, 8); 135 136 byte[] ack_command = new byte[4 + 1 + 4 + 1]; 137 ByteArrayUtil.setInt(ACKNOWLEDGEMENT, ack_command, 0); 139 ack_command[4] = 1; 140 ByteArrayUtil.setInt(SERVER_VERSION, ack_command, 5); 141 ack_command[9] = 0; 142 143 state = 4; 145 146 return ack_command; 148 149 } 162 163 else if (state == 4) { 164 ByteArrayInputStream bin = new ByteArrayInputStream(command); 166 DataInputStream din = new DataInputStream(bin); 167 String default_schema = din.readUTF(); 168 String username = din.readUTF(); 169 String password = din.readUTF(); 170 171 try { 172 boolean good = db_interface.login(default_schema, username, password, 173 db_call_back); 174 if (good == false) { 175 if (authentication_tries >= 12) { 177 close(); 178 } 179 else { 180 ++authentication_tries; 181 return single(USER_AUTHENTICATION_FAILED); 182 } 183 } 184 else { 185 state = 100; 186 return single(USER_AUTHENTICATION_PASSED); 187 } 188 } 189 catch (SQLException e) { } 190 return null; 191 192 } 193 194 else if (state == 100) { 195 return processQuery(command); 197 } 198 199 else { 200 throw new Error ("Illegal state: " + state); 201 } 202 203 } 204 205 209 int getState() { 210 return state; 211 } 212 213 217 private byte[] single(int val) { 218 byte[] buf = new byte[4]; 219 ByteArrayUtil.setInt(val, buf, 0); 220 return buf; 221 } 222 223 226 private byte[] exception(int dispatch_id, SQLException e) 227 throws IOException { 228 229 int code = e.getErrorCode(); 230 String msg = e.getMessage(); 231 if (msg == null) { 232 msg = "NULL exception message"; 233 } 234 String server_msg = ""; 235 String stack_trace = ""; 236 237 if (e instanceof MSQLException) { 238 MSQLException me = (MSQLException) e; 239 server_msg = me.getServerErrorMsg(); 240 stack_trace = me.getServerErrorStackTrace(); 241 } 242 else { 243 StringWriter writer = new StringWriter(); 244 e.printStackTrace(new PrintWriter(writer)); 245 stack_trace = writer.toString(); 246 } 247 248 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 249 DataOutputStream dout = new DataOutputStream(bout); 250 dout.writeInt(dispatch_id); 251 dout.writeInt(EXCEPTION); 252 dout.writeInt(code); 253 dout.writeUTF(msg); 254 dout.writeUTF(stack_trace); 255 256 return bout.toByteArray(); 257 258 } 259 260 264 private byte[] simpleSuccess(int dispatch_id) throws IOException { 265 byte[] buf = new byte[8]; 266 ByteArrayUtil.setInt(dispatch_id, buf, 0); 267 ByteArrayUtil.setInt(SUCCESS, buf, 4); 268 return buf; 269 } 270 271 274 private byte[] processQuery(byte[] command) throws IOException { 275 276 byte[] result; 277 278 int ins = ByteArrayUtil.getInt(command, 0); 280 281 int dispatch_id = ByteArrayUtil.getInt(command, 4); 284 285 if (dispatch_id == -1) { 286 throw new Error ("Special case dispatch id of -1 in query"); 287 } 288 289 if (ins == RESULT_SECTION) { 290 result = resultSection(dispatch_id, command); 291 } 292 else if (ins == QUERY) { 293 result = queryCommand(dispatch_id, command); 294 } 295 else if (ins == PUSH_STREAMABLE_OBJECT_PART) { 296 result = pushStreamableObjectPart(dispatch_id, command); 297 } 298 else if (ins == DISPOSE_RESULT) { 299 result = disposeResult(dispatch_id, command); 300 } 301 else if (ins == STREAMABLE_OBJECT_SECTION) { 302 result = streamableObjectSection(dispatch_id, command); 303 } 304 else if (ins == DISPOSE_STREAMABLE_OBJECT) { 305 result = disposeStreamableObject(dispatch_id, command); 306 } 307 else if (ins == CLOSE) { 308 close(); 309 result = null; 310 } 311 else { 312 throw new Error ("Command (" + ins + ") not understood."); 313 } 314 315 return result; 316 317 } 318 319 322 void dispose() { 323 try { 324 db_interface.dispose(); 325 } 326 catch (Throwable e) { 327 debug.writeException(Lvl.ERROR, e); 328 } 329 } 330 331 332 334 341 private byte[] queryCommand(int dispatch_id, 342 byte[] command) throws IOException { 343 344 ByteArrayInputStream bin = 346 new ByteArrayInputStream(command, 8, command.length - 8); 347 DataInputStream din = new DataInputStream(bin); 348 SQLQuery query = SQLQuery.readFrom(din); 349 350 try { 351 QueryResponse response = db_interface.execQuery(query); 353 354 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 356 DataOutputStream dout = new DataOutputStream(bout); 357 358 dout.writeInt(dispatch_id); 359 dout.writeInt(SUCCESS); 360 361 dout.writeInt(response.getResultID()); 364 dout.writeInt(response.getQueryTimeMillis()); 365 dout.writeInt(response.getRowCount()); 366 int col_count = response.getColumnCount(); 367 dout.writeInt(col_count); 368 for (int i = 0; i < col_count; ++i) { 369 response.getColumnDescription(i).writeTo(dout); 370 } 371 372 return bout.toByteArray(); 373 374 } 375 catch (SQLException e) { 376 return exception(dispatch_id, e); 378 } 379 380 } 381 382 387 private byte[] pushStreamableObjectPart(int dispatch_id, 388 byte[] command) throws IOException { 389 byte type = command[8]; 390 long object_id = ByteArrayUtil.getLong(command, 9); 391 long object_length = ByteArrayUtil.getLong(command, 17); 392 int length = ByteArrayUtil.getInt(command, 25); 393 byte[] ob_buf = new byte[length]; 394 System.arraycopy(command, 29, ob_buf, 0, length); 395 long offset = ByteArrayUtil.getLong(command, 29 + length); 396 397 try { 398 db_interface.pushStreamableObjectPart(type, object_id, object_length, 400 ob_buf, offset, length); 401 402 return simpleSuccess(dispatch_id); 404 405 } 406 catch (SQLException e) { 407 return exception(dispatch_id, e); 408 } 409 410 } 411 412 418 private byte[] resultSection(int dispatch_id, 419 byte[] command) throws IOException { 420 421 int result_id = ByteArrayUtil.getInt(command, 8); 422 int row_number = ByteArrayUtil.getInt(command, 12); 423 int row_count = ByteArrayUtil.getInt(command, 16); 424 425 try { 426 ResultPart block = 428 db_interface.getResultPart(result_id, row_number, row_count); 429 430 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 431 DataOutputStream dout = new DataOutputStream(bout); 432 433 dout.writeInt(dispatch_id); 434 dout.writeInt(SUCCESS); 435 436 int col_count = block.size() / row_count; 440 dout.writeInt(col_count); 441 int bsize = block.size(); 442 for (int index = 0; index < bsize; ++index) { 443 ObjectTransfer.writeTo(dout, block.elementAt(index)); 444 } 445 446 return bout.toByteArray(); 447 } 448 catch (SQLException e) { 449 return exception(dispatch_id, e); 450 } 451 } 452 453 458 private byte[] streamableObjectSection(int dispatch_id, byte[] command) 459 throws IOException { 460 int result_id = ByteArrayUtil.getInt(command, 8); 461 long streamable_object_id = ByteArrayUtil.getLong(command, 12); 462 long offset = ByteArrayUtil.getLong(command, 20); 463 int length = ByteArrayUtil.getInt(command, 28); 464 465 try { 466 StreamableObjectPart ob_part = 467 db_interface.getStreamableObjectPart(result_id, streamable_object_id, 468 offset, length); 469 470 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 471 DataOutputStream dout = new DataOutputStream(bout); 472 473 dout.writeInt(dispatch_id); 474 dout.writeInt(SUCCESS); 475 476 byte[] buf = ob_part.getContents(); 477 dout.writeInt(buf.length); 478 dout.write(buf, 0, buf.length); 479 480 return bout.toByteArray(); 481 } 482 catch (SQLException e) { 483 return exception(dispatch_id, e); 484 } 485 486 } 487 488 493 private byte[] disposeStreamableObject(int dispatch_id, byte[] command) 494 throws IOException { 495 int result_id = ByteArrayUtil.getInt(command, 8); 496 long streamable_object_id = ByteArrayUtil.getLong(command, 12); 497 498 try { 499 db_interface.disposeStreamableObject(result_id, streamable_object_id); 501 502 return simpleSuccess(dispatch_id); 504 505 } 506 catch (SQLException e) { 507 return exception(dispatch_id, e); 508 } 509 } 510 511 516 private byte[] disposeResult(int dispatch_id, 517 byte[] command) throws IOException { 518 519 int result_id = ByteArrayUtil.getInt(command, 8); 521 522 try { 523 db_interface.disposeResult(result_id); 525 return simpleSuccess(dispatch_id); 527 } 528 catch (SQLException e) { 529 return exception(dispatch_id, e); 530 } 531 } 532 533 534 535 536 537 538 540 552 public abstract void sendEvent(byte[] event_msg) throws IOException; 553 554 557 public abstract void close() throws IOException; 558 559 562 public abstract boolean isClosed() throws IOException; 563 564 566 public final void finalize() throws Throwable { 567 super.finalize(); 568 try { 569 dispose(); 570 } 571 catch (Throwable e) { } 572 } 573 574 } 575 | Popular Tags |