1 24 25 package com.mckoi.database.jdbc; 26 27 import com.mckoi.database.control.DBConfig; 28 import com.mckoi.database.control.DefaultDBConfig; 29 30 import java.sql.*; 31 import java.io.*; 32 import java.util.Properties ; 33 import java.util.Enumeration ; 34 import java.util.StringTokenizer ; 35 import java.util.Vector ; 36 import java.util.Hashtable ; 37 import java.net.URL ; 38 import java.net.MalformedURLException ; 39 40 80 81 public class MDriver implements Driver { 82 83 static final int DRIVER_MAJOR_VERSION = 1; 86 static final int DRIVER_MINOR_VERSION = 0; 87 88 static final String DRIVER_NAME = "Mckoi JDBC Driver"; 90 static final String DRIVER_VERSION = 92 "" + DRIVER_MAJOR_VERSION + "." + DRIVER_MINOR_VERSION; 93 94 95 private static final String mckoi_protocol_url = "jdbc:mckoi:"; 97 98 99 102 private static boolean registered = false; 103 104 105 107 110 public synchronized static void register() { 111 if (registered == false) { 112 try { 113 java.sql.DriverManager.registerDriver(new MDriver()); 114 registered = true; 115 } 116 catch (SQLException e) { 117 e.printStackTrace(); 118 } 119 } 120 } 121 122 124 127 static int QUERY_TIMEOUT = Integer.MAX_VALUE; 128 129 134 private Hashtable local_session_map; 135 136 140 public MDriver() { 141 local_session_map = new Hashtable (); 142 } 143 144 150 private static void parseEncodedVariables(String url_vars, Properties info) { 151 152 StringTokenizer tok = new StringTokenizer (url_vars, "&"); 154 while (tok.hasMoreTokens()) { 155 String token = tok.nextToken().trim(); 156 int split_point = token.indexOf("="); 157 if (split_point > 0) { 158 String key = token.substring(0, split_point).toLowerCase(); 159 String value = token.substring(split_point + 1); 160 info.put(key, value); 162 } 163 else { 164 System.err.println("Ignoring url variable: '" + token + "'"); 165 } 166 } 168 } 169 170 177 private static LocalBootable createDefaultLocalBootable() 178 throws SQLException { 179 try { 180 Class c = Class.forName( 181 "com.mckoi.database.jdbcserver.DefaultLocalBootable"); 182 return (LocalBootable) c.newInstance(); 183 } 184 catch (Throwable e) { 185 throw new SQLException( 187 "I was unable to find the class that manages local database " + 188 "connections. This means you may not have included the correct " + 189 "library in your classpath. Make sure that either mckoidb.jar " + 190 "is in your classpath or your classpath references the complete " + 191 "Mckoi SQL database class hierarchy."); 192 } 193 } 194 195 202 private synchronized Object [] connectToLocal(String url, String address_part, 203 Properties info) throws SQLException { 204 205 String schema_name = "APP"; 208 DatabaseInterface db_interface; 209 210 int url_start = address_part.indexOf("?"); 212 if (url_start == -1) { 213 url_start = address_part.length(); 214 } 215 216 String config_path = address_part.substring(8, url_start); 218 219 if (config_path.length() == 0) { 221 config_path = "./db.conf"; 222 } 223 224 config_path = config_path.replace('\\', '/'); 226 227 if (config_path.startsWith("jar:") || 229 config_path.startsWith("file:/") || 230 config_path.startsWith("ftp:/") || 231 config_path.startsWith("http:/") || 232 config_path.startsWith("https:/")) { 233 } 235 else { 236 237 String abs_path; 239 String post_abs_path; 240 int schem_del = config_path.indexOf(".conf/"); 241 if (schem_del == -1) { 242 abs_path = config_path; 243 post_abs_path = ""; 244 } 245 else { 246 abs_path = config_path.substring(0, schem_del + 5); 247 post_abs_path = config_path.substring(schem_del + 5); 248 } 249 250 254 259 int jar_delim_i = abs_path.indexOf("!/"); 260 String path_part = abs_path; 261 String rest_part = ""; 262 String pre = "file:/"; 263 if (jar_delim_i != -1) { 264 path_part = abs_path.substring(0, jar_delim_i); 265 rest_part = abs_path.substring(jar_delim_i); 266 pre = "jar:file:/"; 267 } 268 269 File f = new File(path_part); 273 if (!f.exists() && !path_part.startsWith("/")) { 274 f = new File("/" + path_part); 275 if (!f.exists()) { 276 throw new SQLException("Unable to find file: " + path_part); 277 } 278 } 279 config_path = pre + f.getAbsolutePath() + rest_part + post_abs_path; 281 config_path = config_path.replace('\\', '/'); 285 } 286 287 int schema_del_i = config_path.toLowerCase().indexOf(".conf/"); 293 if (schema_del_i > 0 && 294 schema_del_i + 6 < config_path.length()) { 295 schema_name = config_path.substring(schema_del_i + 6); 296 config_path = config_path.substring(0, schema_del_i + 5); 297 } 298 299 String url_vars = ""; 301 if (url_start < address_part.length()) { 302 url_vars = address_part.substring(url_start + 1).trim(); 303 } 304 305 String session_key = config_path.toLowerCase(); 307 LocalBootable local_bootable = 308 (LocalBootable) local_session_map.get(session_key); 309 if (local_bootable == null) { 311 local_bootable = createDefaultLocalBootable(); 312 local_session_map.put(session_key, local_bootable); 313 } 314 315 if (local_bootable.isBooted()) { 317 db_interface = local_bootable.connectToJVM(); 319 } 320 else { 321 323 InputStream config_in; 325 if (!config_path.startsWith("file:/")) { 326 URL config_url; 328 try { 329 config_url = new URL (config_path); 330 } 331 catch (MalformedURLException e) { 332 throw new SQLException("Malformed URL: " + config_path); 333 } 334 335 try { 336 config_in = config_url.openConnection().getInputStream(); 338 } 339 catch (IOException e) { 340 throw new SQLException("Unable to open configuration file. " + 341 "I tried looking at '" + config_url.toString() + "'"); 342 } 343 } 344 else { 345 try { 346 config_in = new FileInputStream(new File(config_path.substring(6))); 348 } 349 catch (IOException e) { 350 throw new SQLException("Unable to open configuration file: " + 351 config_path); 352 } 353 354 } 355 356 File root_path; 359 if (config_path.startsWith("jar:file:/") || 361 config_path.startsWith("file:/")) { 362 363 int start_i = config_path.indexOf(":/"); 364 365 int file_end_i = config_path.indexOf("!"); 368 String config_file_part; 369 if (file_end_i == -1) { 370 config_file_part = config_path.substring(start_i + 2); 371 } 372 else { 373 config_file_part = config_path.substring(start_i + 2, file_end_i); 374 } 375 376 File absolute_config_file = new File( 377 new File(config_file_part).getAbsolutePath()); 378 root_path = new File(absolute_config_file.getParent()); 379 } 380 else { 381 root_path = new File("."); 384 } 385 386 DefaultDBConfig config = new DefaultDBConfig(root_path); 388 try { 389 config.loadFromStream(config_in); 390 config_in.close(); 391 } 392 catch (IOException e) { 393 throw new SQLException("Error reading configuration file: " + 394 config_path + " Reason: " + e.getMessage()); 395 } 396 397 parseEncodedVariables(url_vars, info); 399 400 boolean create_db = false; 401 boolean create_db_if_not_exist = false; 402 create_db = info.getProperty("create", "").equals("true"); 403 create_db_if_not_exist = 404 info.getProperty("boot_or_create", "").equals("true") || 405 info.getProperty("create_or_boot", "").equals("true"); 406 407 Enumeration prop_keys = info.keys(); 409 while (prop_keys.hasMoreElements()) { 410 String key = prop_keys.nextElement().toString(); 411 if (!key.equals("user") && !key.equals("password")) { 412 config.setValue(key, (String ) info.get(key)); 413 } 414 } 415 416 boolean database_exists = local_bootable.checkExists(config); 418 419 if (create_db_if_not_exist && !database_exists) { 422 create_db = true; 423 } 424 425 if (create_db && database_exists) { 428 throw new SQLException( 429 "Can not create database because a database already exists."); 430 } 431 if (!create_db && !database_exists) { 433 throw new SQLException( 434 "Can not find a database to start. Either the database needs to " + 435 "be created or the 'database_path' property of the configuration " + 436 "must be set to the location of the data files."); 437 } 438 439 if (create_db) { 441 String username = info.getProperty("user", ""); 442 String password = info.getProperty("password", ""); 443 444 db_interface = local_bootable.create(username, password, config); 445 } 446 else { 448 db_interface = local_bootable.boot(config); 449 } 450 } 451 452 Object [] ret = new Object [2]; 454 ret[0] = db_interface; 455 ret[1] = schema_name; 456 457 return ret; 458 459 } 460 461 462 464 public Connection connect(String url, Properties info) throws SQLException { 465 if (!acceptsURL(url)) { 467 return null; 469 } 470 471 DatabaseInterface db_interface; 472 String default_schema = "APP"; 473 474 int row_cache_size; 475 int max_row_cache_size; 476 477 String address_part = url.substring(url.indexOf(mckoi_protocol_url) + 478 mckoi_protocol_url.length()); 479 if (address_part.startsWith("local://")) { 482 483 Object [] ret_list = connectToLocal(url, address_part, info); 485 db_interface = (DatabaseInterface) ret_list[0]; 486 default_schema = (String ) ret_list[1]; 487 488 row_cache_size = 43; 490 max_row_cache_size = 4092000; 491 492 } 493 else { 494 int port = 9157; 495 String host = "127.0.0.1"; 496 497 if (address_part.startsWith("//")) { 499 500 String args_string = ""; 501 int arg_part = address_part.indexOf('?', 2); 502 if (arg_part != -1) { 503 args_string = address_part.substring(arg_part + 1); 504 address_part = address_part.substring(0, arg_part); 505 } 506 507 509 int end_address = address_part.indexOf("/", 2); 510 if (end_address == -1) { 511 end_address = address_part.length(); 512 } 513 String remote_address = address_part.substring(2, end_address); 514 int delim = remote_address.indexOf(':'); 515 if (delim == -1) { 516 delim = remote_address.length(); 517 } 518 host = remote_address.substring(0, delim); 519 if (delim < remote_address.length() - 1) { 520 port = Integer.parseInt(remote_address.substring(delim + 1)); 521 } 522 523 525 String schema_part = ""; 527 if (end_address < address_part.length()) { 528 schema_part = address_part.substring(end_address + 1); 529 } 530 String schema_string = schema_part; 531 int schema_end = schema_part.indexOf('/'); 532 if (schema_end != -1) { 533 schema_string = schema_part.substring(0, schema_end); 534 } 535 else { 536 schema_end = schema_part.indexOf('?'); 537 if (schema_end != -1) { 538 schema_string = schema_part.substring(0, schema_end); 539 } 540 } 541 542 544 if (!args_string.equals("")) { 546 parseEncodedVariables(args_string, info); 548 } 549 550 if (schema_string.length() > 0) { 552 default_schema = schema_string; 553 } 554 555 } 556 else { 557 if (address_part.trim().length() > 0) { 558 throw new SQLException("Malformed URL: " + address_part); 559 } 560 } 561 562 567 try { 576 Thread.sleep(85); 577 } 578 catch (InterruptedException e) { } 579 580 TCPStreamDatabaseInterface tcp_db_interface = 582 new TCPStreamDatabaseInterface(host, port); 583 tcp_db_interface.connectToDatabase(); 585 586 db_interface = tcp_db_interface; 587 588 row_cache_size = 4111; 590 max_row_cache_size = 8192000; 591 592 } 593 594 596 MConnection connection = new MConnection(url, db_interface, 598 row_cache_size, max_row_cache_size); 599 connection.login(info, default_schema); 601 602 return connection; 603 } 604 605 public boolean acceptsURL(String url) throws SQLException { 606 return url.startsWith(mckoi_protocol_url) || 607 url.startsWith(":" + mckoi_protocol_url); 608 } 609 610 public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) 611 throws SQLException { 612 615 return new DriverPropertyInfo[0]; 617 } 618 619 public int getMajorVersion() { 620 return DRIVER_MAJOR_VERSION; 621 } 622 623 public int getMinorVersion() { 624 return DRIVER_MINOR_VERSION; 625 } 626 627 public boolean jdbcCompliant() { 628 return false; 630 } 631 632 } 633 | Popular Tags |