src/org/objectweb/cjdbc/driver/Driver.java

説明を見る。
00001 00026 package org.objectweb.cjdbc.driver; 00027 00028 import java.io.IOException; 00029 import java.net.Socket; 00030 import java.sql.DriverPropertyInfo; 00031 import java.sql.SQLException; 00032 import java.util.ArrayList; 00033 import java.util.Enumeration; 00034 import java.util.HashMap; 00035 import java.util.Hashtable; 00036 import java.util.Properties; 00037 import java.util.Random; 00038 import java.util.StringTokenizer; 00039 00040 import javax.net.SocketFactory; 00041 00042 import org.objectweb.cjdbc.common.net.SSLConfiguration; 00043 import org.objectweb.cjdbc.common.net.SocketFactoryFactory; 00044 import org.objectweb.cjdbc.common.sql.filters.AbstractBlobFilter; 00045 import org.objectweb.cjdbc.common.stream.CJDBCInputStream; 00046 import org.objectweb.cjdbc.common.stream.CJDBCOutputStream; 00047 import org.objectweb.cjdbc.common.util.Constants; 00048 import org.objectweb.cjdbc.controller.core.ControllerConstants; 00049 import org.objectweb.cjdbc.driver.protocol.Commands; 00050 00105 public class Driver implements java.sql.Driver 00106 { 00108 public static final int MAJOR_VERSION = Constants 00109 .getMajorVersion(); 00110 00112 public static final int MINOR_VERSION = Constants 00113 .getMinorVersion(); 00114 00116 private static final String HOST_PROPERTY = "HOST"; 00117 private static final String PORT_PROPERTY = "PORT"; 00118 private static final String CONTROLLER_PROPERTY = "CONTROLLER"; 00119 protected static final String DATABASE_PROPERTY = "DATABASE"; 00120 protected static final String USER_PROPERTY = "user"; 00121 protected static final String PASSWORD_PROPERTY = "password"; 00122 protected static final String PARAMETER_PROPERTY = "parameter"; 00123 protected static final String BOOLEAN_TRUE_PROPERTY = "booleanTrue"; 00124 protected static final String BOOLEAN_FALSE_PROPERTY = "booleanFalse"; 00125 protected static final String ESCAPE_BACKSLASH_PROPERTY = "escapeBackslash"; 00126 protected static final String ESCAPE_SINGLE_QUOTE_PROPERTY = "escapeSingleQuote"; 00127 protected static final String ESCAPE_CHARACTER_PROPERTY = "escapeCharacter"; 00128 protected static final String DRIVER_PROCESSED_PROPERTY = "driverProcessed"; 00129 00131 private static final String HOST_PROPERTY_DESCRIPTION = "Hostname of C-JDBC controller"; 00132 private static final String PORT_PROPERTY_DESCRIPTION = "Port number of C-JDBC controller"; 00133 private static final String DATABASE_PROPERTY_DESCRIPTION = "Database name"; 00134 private static final String USER_PROPERTY_DESCRIPTION = "Username to authenticate as"; 00135 private static final String PASSWORD_PROPERTY_DESCRIPTION = "Password to use for authentication"; 00136 private static final String BOOLEAN_TRUE_PROPERTY_DESCRIPTION = "Use this value for the 'true' value when using PreparedStatement.setBoolean method"; 00137 private static final String BOOLEAN_FALSE_PROPERTY_DESCRIPTION = "Use this value for the 'false' value when using PreparedStatement.setBoolean method"; 00138 private static final String ESCAPE_BACKSLASH_PROPERTY_DESCRIPTION = "Set this to true to escape backslashes when performing escape processing of PreparedStatements"; 00139 private static final String ESCAPE_SINGLE_QUOTE_PROPERTY_DESCRIPTION = "Set this to true to escape single quotes (') when performing escape processing of PreparedStatements"; 00140 private static final String ESCAPE_CHARACTER_PROPERTY_DESCRIPTION = "Use this character to prepend and append to the values when performing escape processing of PreparedStatements"; 00141 private static final String DRIVER_PROCESSED_PROPERTY_DESCRIPTION = "Set this to false to let queries be passed and prepared for each individual backend"; 00142 00144 private static final String CJDBC_URL_HEADER = "jdbc:cjdbc://"; 00145 00147 private static final int CJDBC_URL_HEADER_LENGTH = CJDBC_URL_HEADER 00148 .length(); 00149 00154 private HashMap controllerCache = new HashMap(); 00155 00157 private HashMap dbNameCache = new HashMap(); 00158 00160 protected ArrayList pendingConnectionClosing = new ArrayList(); 00161 protected boolean connectionClosingThreadisAlive = false; 00162 00164 private String currentControllerURL = null; 00165 private ArrayList controllerConfig = null; 00166 private ControllerInfo currentControllerConfig = null; 00167 private String currentDatabase = null; 00168 private Random random; 00169 private int controllerConfigArraySize; 00170 private int connectionRequestSinceControllerFailure = 0; 00171 // Retry to reconnect to a controller after RETRY_CONTROLLER_AFTER_FAILURE 00172 // connection requests have been treated since the failure. 00173 private static final int RETRY_CONTROLLER_AFTER_FAILURE = 10; 00174 00175 // The static initializer registers ourselves with the DriverManager 00176 // and try to bind the C-JDBC Controller 00177 static 00178 { 00179 // Register with the DriverManager (see JDBC API Tutorial and Reference, 00180 // Second Edition p. 941) 00181 try 00182 { 00183 java.sql.DriverManager.registerDriver(new Driver()); 00184 } 00185 catch (SQLException e) 00186 { 00187 throw new RuntimeException("Unable to register C-JDBC driver"); 00188 } 00189 } 00190 00195 public Driver() 00196 { 00197 // Required for Class.forName().newInstance() 00198 random = new Random(System.currentTimeMillis()); 00199 } 00200 00215 public java.sql.Connection connect(String url, Properties info) 00216 throws SQLException 00217 { 00218 if (url == null) 00219 throw new SQLException("Invalid null URL in connect"); 00220 00226 if (!url.toLowerCase().startsWith(CJDBC_URL_HEADER)) 00227 return null; 00228 00229 String user = null; 00230 if (info != null) 00231 user = info.getProperty(USER_PROPERTY); 00232 else 00233 { 00234 info = new Properties(); 00235 } 00236 00237 // Parse url to get parameters 00238 Hashtable props = this.parseUrlParams(url); 00239 if (props != null) 00240 info.putAll(props); 00241 00242 if (user == null || user.equals("")) 00243 { 00244 if ((user = info.getProperty(USER_PROPERTY)) == null) 00245 throw new SQLException("Invalid null user name in connect"); 00246 } 00247 00248 String password = info.getProperty(PASSWORD_PROPERTY); 00249 if (password == null) 00250 { 00251 throw new SQLException("Invalid null password in connect"); 00252 } 00253 00254 // SSL enabled ? 00255 SSLConfiguration ssl = null; 00256 if ("true".equals(System.getProperty("cjdbc.ssl.enabled"))) 00257 { 00258 ssl = SSLConfiguration.getDefaultConfig(); 00259 } 00260 00261 // Check if there is a connection that is about to be closed that could 00262 // be reused. We take the bet that if a connection has been released by 00263 // a client, in the general case, it will reuse the same connection. 00264 // As we need to keep the work in the synchronized block as minimal as 00265 // possible, we have to extract the string comparison (url,name,password) 00266 // from the sync block. This way, we cannot just read/compare/take the 00267 // connection without synchronizing the whole thing. A solution is to 00268 // systematically extract the first available connection in the sync block, 00269 // and do the checkings outside the block. If we fail, we re-sync to put 00270 // the connection back but in practice it is almost always a success and 00271 // we don't really care to pay this extra cost once in a while. 00272 try 00273 { 00274 Connection c; 00275 synchronized (pendingConnectionClosing) 00276 { 00277 // Take the last one to prevent shifting all elements 00278 c = (Connection) pendingConnectionClosing 00279 .remove(pendingConnectionClosing.size() - 1); 00280 } 00281 if (url.equals(c.getURL()) && user.equals(c.getUserName()) 00282 && password.equals(c.getPassword())) 00283 { // Great! Take this one. 00284 c.isClosed = false; 00285 return setParametersOnConnection(info, c); 00286 } 00287 else 00288 // Put this connection back, it is not good for us 00289 synchronized (pendingConnectionClosing) 00290 { 00291 pendingConnectionClosing.add(c); 00292 } 00293 } 00294 catch (IndexOutOfBoundsException ignore) 00295 { 00296 // No connection available 00297 } 00298 00299 int retry = 2; 00300 int picked; 00301 while (retry > 0) 00302 { 00303 // Check if the last url used was the same, if yes we re-use the 00304 // same controller and connection point. 00305 synchronized (this) 00306 { 00307 if (!url.equals(currentControllerURL) 00308 || (connectionRequestSinceControllerFailure >= RETRY_CONTROLLER_AFTER_FAILURE) 00309 || ((controllerConfig != null) && (controllerConfig.size() == 0))) 00310 { // Too bad, all caches missed 00311 ControllerInfo[] controllerConfigArray = (ControllerInfo[]) controllerCache 00312 .get(url); 00313 if (controllerConfigArray == null) // Not in the cache 00314 { 00315 parseURL(url); 00316 controllerConfigArray = (ControllerInfo[]) controllerCache.get(url); 00317 } 00318 controllerConfig = new ArrayList(); 00319 controllerConfigArraySize = controllerConfigArray.length; 00320 for (int i = 0; i < controllerConfigArraySize; i++) 00321 controllerConfig.add(controllerConfigArray[i]); 00322 00323 currentControllerURL = url; 00324 currentDatabase = (String) dbNameCache.get(url); 00325 if (currentDatabase == null) 00326 throw new SQLException("Database name cache failure"); 00327 00328 // Give all controllers a chance 00329 retry = controllerConfig.size(); 00330 connectionRequestSinceControllerFailure = 0; 00331 } 00332 } 00333 00334 int size = controllerConfig.size(); 00335 if (size < controllerConfigArraySize) 00336 connectionRequestSinceControllerFailure++; 00337 00338 // Pick one controller randomly among the controllers that have not been 00339 // tried yet. 00340 picked = random.nextInt(size); 00341 currentControllerConfig = (ControllerInfo) controllerConfig.get(picked); 00342 00343 boolean sentVdbName = false; 00344 boolean sentUserInfo = false; 00345 try 00346 { 00347 // Connect to the controller 00348 Socket socket = null; 00349 if (ssl == null) 00350 { 00351 // no ssl - we use ordinary socket 00352 socket = new Socket(currentControllerConfig.getHostname(), 00353 currentControllerConfig.getPort()); 00354 } 00355 else 00356 { 00357 SocketFactory sslFact = SocketFactoryFactory.createFactory(ssl); 00358 socket = sslFact.createSocket(currentControllerConfig.getHostname(), 00359 currentControllerConfig.getPort()); 00360 } 00361 00362 // Disable Nagle algorithm else small messages are not sent 00363 // (at least under Linux) even if we flush the output stream. 00364 socket.setTcpNoDelay(true); 00365 00366 CJDBCOutputStream out = new CJDBCOutputStream(socket); 00367 // Send protocol version and database name 00368 out.writeInt(Commands.ProtocolVersion); 00369 out.writeUTF(currentDatabase); 00370 out.flush(); 00371 sentVdbName = true; 00372 00373 // Send user information 00374 out.writeUTF(user); 00375 out.writeUTF(password); 00376 out.flush(); 00377 sentUserInfo = true; 00378 00379 CJDBCInputStream in; 00380 boolean needSkeleton; 00381 AbstractBlobFilter filter = null; 00382 try 00383 { 00384 // Create input stream only here else it will block 00385 in = new CJDBCInputStream(socket); 00386 00387 Object response = in.readObject(); 00388 if (response instanceof Boolean) 00389 { 00390 needSkeleton = ((Boolean) response).booleanValue(); 00391 String sfilter = in.readUTF(); 00392 filter = AbstractBlobFilter.getBlobFilterInstance(sfilter); 00393 } 00394 else if (response instanceof SQLException) 00395 throw (SQLException) response; 00396 else 00397 throw new SQLException("Error during connection (received " 00398 + response + ")"); 00399 } 00400 catch (IOException e) 00401 { 00402 currentControllerURL = null; 00403 throw new SQLException("Authentication failed"); 00404 } 00405 return setParametersOnConnection(info, new Connection(this, socket, in, 00406 out, url, user, password, needSkeleton, filter)); 00407 } 00408 catch (Exception re) 00409 { 00410 controllerConfig.remove(picked); 00411 retry--; 00412 if (retry == 0) 00413 { 00414 if (!sentVdbName) 00415 throw new SQLException("Unable to connect to controller on " 00416 + currentControllerConfig.getHostname() + ":" 00417 + currentControllerConfig.getPort() + " (" + re + ")"); 00418 else if (!sentUserInfo) 00419 throw new SQLException( 00420 "Unable to connect to the virtual database (virtual database name is probably not correct)"); 00421 else 00422 throw new SQLException( 00423 "Unable to connect to the virtual database (" + re + ")"); 00424 } 00425 else 00426 { // Reset if no more controllers in the list 00427 if (controllerConfig.isEmpty()) 00428 currentControllerURL = null; 00429 } 00430 } 00431 } 00432 throw new SQLException( 00433 "Unable to connect to the virtual database - Unexpected error."); 00434 } 00435 00446 public synchronized boolean acceptsURL(String url) throws SQLException 00447 { 00448 try 00449 { 00450 parseURL(url); 00451 return true; 00452 } 00453 catch (SQLException e) 00454 { 00455 return false; 00456 } 00457 } 00458 00466 synchronized Hashtable parseURL(String url) throws SQLException 00467 { 00468 // Find the hostname and check for URL correctness 00469 if (url == null) 00470 { 00471 throw new IllegalArgumentException( 00472 "Illegal null URL in parseURL(String) method"); 00473 } 00474 00475 if (!url.toLowerCase().startsWith(CJDBC_URL_HEADER)) 00476 throw new SQLException("Malformed header from URL '" + url 00477 + "' (expected '" + CJDBC_URL_HEADER + "')"); 00478 else 00479 { 00480 // Initialize return 00481 Hashtable result = new Hashtable(); 00482 00483 // Get the controllers list 00484 int nextSlash = url.indexOf('/', CJDBC_URL_HEADER_LENGTH); 00485 if (nextSlash == -1) 00486 // Missing '/' between hostname and database name. 00487 throw new SQLException("Malformed URL '" + url + "' (expected '" 00488 + CJDBC_URL_HEADER + "<hostname>/<database>')"); 00489 00490 // Found end of database name 00491 int questionMark = url.indexOf('?', nextSlash); 00492 questionMark = (questionMark == -1) 00493 ? url.indexOf(';', nextSlash) 00494 : questionMark; 00495 00496 String controllerURLs = url.substring(CJDBC_URL_HEADER_LENGTH, nextSlash); 00497 // Check the validity of each controller in the list 00498 StringTokenizer controllers = new StringTokenizer(controllerURLs, ",", 00499 true); 00500 int tokenNumber = controllers.countTokens(); 00501 ArrayList list = new ArrayList(); 00502 00503 int i = 0; 00504 String s; 00505 boolean lastTokenWasComma = false; 00506 while (controllers.hasMoreTokens()) 00507 { 00508 s = controllers.nextToken().trim(); 00509 if (s.equals(",")) 00510 { 00511 if (lastTokenWasComma || (i == 0) || (i == tokenNumber - 1)) 00512 // ',' cannot be the first or the last token 00513 // another ',' cannot follow a ',' 00514 throw new SQLException("Syntax error in controller list '" 00515 + controllerURLs + "' from URL '" + url + "'"); 00516 else 00517 { 00518 lastTokenWasComma = true; 00519 continue; 00520 } 00521 } 00522 lastTokenWasComma = false; 00523 list.add(parseController(s)); 00524 i++; 00525 } 00526 00527 ControllerInfo[] controllerList = new ControllerInfo[i]; 00528 for (int j = 0; j < i; j++) 00529 { 00530 controllerList[j] = (ControllerInfo) (list.get(j)); 00531 } 00532 // Add controller list to the result 00533 result.put(CONTROLLER_PROPERTY, controllerList); 00534 00535 // Check database name validity 00536 String databaseName = (questionMark == -1) ? url.substring(nextSlash + 1, 00537 url.length()) : url.substring(nextSlash + 1, questionMark); 00538 Character c = validDatabaseName(databaseName); 00539 if (c != null) 00540 throw new SQLException( 00541 "Unable to validate database name (unacceptable character '" + c 00542 + "' in database '" + databaseName + "' from URL '" + url 00543 + "')"); 00544 00545 // Add database name to result 00546 result.put(DATABASE_PROPERTY, databaseName); 00547 00548 // Finally, add the controllers list and database name to the caches 00549 controllerCache.put(url, controllerList); 00550 dbNameCache.put(url, databaseName); 00551 00552 // Get the parameters from the url 00553 Hashtable params = parseUrlParams(url); 00554 if (params != null) 00555 result.put(PARAMETER_PROPERTY, params); 00556 return result; 00557 } 00558 } 00559 00574 private java.sql.Connection setParametersOnConnection(Properties props, 00575 org.objectweb.cjdbc.driver.Connection connection) 00576 { 00577 String booleanTrue = props.getProperty(BOOLEAN_TRUE_PROPERTY); 00578 if (booleanTrue != null) 00579 connection.setPreparedStatementBooleanTrue(booleanTrue); 00580 String booleanFalse = props.getProperty(BOOLEAN_FALSE_PROPERTY); 00581 if (booleanFalse != null) 00582 connection.setPreparedStatementBooleanFalse(booleanFalse); 00583 String escapeBaskslash = props.getProperty(ESCAPE_BACKSLASH_PROPERTY); 00584 if (escapeBaskslash != null) 00585 connection 00586 .setEscapeBackslash(new Boolean(escapeBaskslash).booleanValue()); 00587 String escapeQuote = props.getProperty(ESCAPE_SINGLE_QUOTE_PROPERTY); 00588 if (escapeQuote != null) 00589 connection.setEscapeSingleQuote(new Boolean(escapeQuote).booleanValue()); 00590 00591 String escapeChar = props.getProperty(ESCAPE_CHARACTER_PROPERTY); 00592 if (escapeChar != null) 00593 connection.setEscapeChar(escapeChar); 00594 00595 String driverProcessed = props.getProperty(DRIVER_PROCESSED_PROPERTY); 00596 if (driverProcessed != null) 00597 connection.setDriverProcessed(Boolean.valueOf(driverProcessed) 00598 .booleanValue()); 00599 00600 return connection; 00601 } 00602 00609 protected String getUrlFromProperties(Hashtable props) 00610 { 00611 StringBuffer sb = new StringBuffer(); 00612 sb.append(CJDBC_URL_HEADER); 00613 ControllerInfo[] controllerList = (ControllerInfo[]) props 00614 .get(CONTROLLER_PROPERTY); 00615 for (int i = 0; i < controllerList.length; i++) 00616 { 00617 if (i == 0) 00618 sb.append(controllerList[i].toString()); 00619 else 00620 sb.append("," + controllerList[i].toString()); 00621 } 00622 sb.append("/" + props.get(DATABASE_PROPERTY)); 00623 Hashtable params = (Hashtable) props.get(PARAMETER_PROPERTY); 00624 if (params != null) 00625 { 00626 Enumeration paramsKeys = params.keys(); 00627 String element = null; 00628 while (paramsKeys.hasMoreElements()) 00629 { 00630 if (element == null) 00631 sb.append("?"); 00632 else 00633 sb.append("&"); 00634 element = (String) paramsKeys.nextElement(); 00635 sb.append(element + "=" + params.get(paramsKeys)); 00636 } 00637 } 00638 return sb.toString(); 00639 } 00640 00641 private Hashtable parseUrlParams(String url) throws SQLException 00642 { 00643 Hashtable props; 00644 props = parseUrlParams(url, '?', "&", "="); 00645 if (props == null) 00646 { 00647 props = parseUrlParams(url, ';', ";", "="); 00648 } 00649 return props; 00650 } 00651 00652 private Hashtable parseUrlParams(String url, char mark, String link, 00653 String equal) throws SQLException 00654 { 00655 int questionMark = url.indexOf(mark, url.lastIndexOf('/')); 00656 if (questionMark == -1) 00657 return null; 00658 else 00659 { 00660 Hashtable props = new Hashtable(); 00661 String parameters = url.substring(questionMark + 1); 00662 StringTokenizer st1 = new StringTokenizer(parameters, link); 00663 while (st1.hasMoreTokens()) 00664 { 00665 String param = st1.nextToken(); 00666 StringTokenizer st2 = new StringTokenizer(param, equal); 00667 if (st2.hasMoreTokens()) 00668 { 00669 try 00670 { 00671 String paramName = st2.nextToken(); 00672 String paramValue = (st2.hasMoreTokens()) ? st2.nextToken() : ""; 00673 props.put(paramName, paramValue); 00674 } 00675 catch (Exception e) 00676 { 00677 throw new SQLException("Invalid parameter in URL"); 00678 } 00679 } 00680 } 00681 return props; 00682 } 00683 } 00684 00693 private ControllerInfo parseController(String controller) throws SQLException 00694 { 00695 ControllerInfo controllerInfo = new ControllerInfo(); 00696 00697 // Check controller syntax 00698 StringTokenizer controllerURL = new StringTokenizer(controller, ":", true); 00699 00700 // Get hostname 00701 controllerInfo.setHostname(controllerURL.nextToken()); 00702 Character c = validHostname(controllerInfo.getHostname()); 00703 if (c != null) 00704 throw new SQLException( 00705 "Unable to validate hostname (unacceptable character '" + c 00706 + "' in hostname '" + controllerInfo.getHostname() 00707 + "' from the URL part '" + controller + "')"); 00708 00709 if (!controllerURL.hasMoreTokens()) 00710 controllerInfo.setPort(ControllerConstants.DEFAULT_PORT); 00711 else 00712 { 00713 controllerURL.nextToken(); // should be ':' 00714 if (!controllerURL.hasMoreTokens()) 00715 controllerInfo.setPort(ControllerConstants.DEFAULT_PORT); 00716 else 00717 { // Get the port number 00718 String port = controllerURL.nextToken(); 00719 if (controllerURL.hasMoreTokens()) 00720 throw new SQLException( 00721 "Invalid controller definition with more than one semicolon in URL part '" 00722 + controller + "'"); 00723 00724 // Check the port number validity 00725 try 00726 { 00727 controllerInfo.setPort(Integer.parseInt(port)); 00728 } 00729 catch (NumberFormatException ne) 00730 { 00731 throw new SQLException( 00732 "Unable to validate port number (unacceptable port number '" 00733 + port + "' in this URL part '" + controller + "')"); 00734 } 00735 } 00736 } 00737 return controllerInfo; 00738 } 00739 00761 public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) 00762 throws SQLException 00763 { 00764 DriverPropertyInfo hostProp = new DriverPropertyInfo(HOST_PROPERTY, info 00765 .getProperty(HOST_PROPERTY)); 00766 hostProp.required = true; 00767 hostProp.description = HOST_PROPERTY_DESCRIPTION; 00768 00769 DriverPropertyInfo portProp = new DriverPropertyInfo(PORT_PROPERTY, info 00770 .getProperty(PORT_PROPERTY, Integer 00771 .toString(ControllerConstants.DEFAULT_PORT))); 00772 portProp.required = false; 00773 portProp.description = PORT_PROPERTY_DESCRIPTION; 00774 00775 DriverPropertyInfo databaseProp = new DriverPropertyInfo(DATABASE_PROPERTY, 00776 info.getProperty(DATABASE_PROPERTY)); 00777 databaseProp.required = true; 00778 databaseProp.description = DATABASE_PROPERTY_DESCRIPTION; 00779 00780 DriverPropertyInfo userProp = new DriverPropertyInfo(USER_PROPERTY, info 00781 .getProperty(USER_PROPERTY)); 00782 userProp.required = true; 00783 userProp.description = USER_PROPERTY_DESCRIPTION; 00784 00785 DriverPropertyInfo passwordProp = new DriverPropertyInfo(PASSWORD_PROPERTY, 00786 info.getProperty(PASSWORD_PROPERTY)); 00787 passwordProp.required = true; 00788 passwordProp.description = PASSWORD_PROPERTY_DESCRIPTION; 00789 00790 DriverPropertyInfo escapeCharProp = new DriverPropertyInfo( 00791 ESCAPE_CHARACTER_PROPERTY, info.getProperty(ESCAPE_CHARACTER_PROPERTY)); 00792 escapeCharProp.required = false; 00793 escapeCharProp.description = ESCAPE_CHARACTER_PROPERTY_DESCRIPTION; 00794 00795 DriverPropertyInfo escapeBackProp = new DriverPropertyInfo( 00796 ESCAPE_BACKSLASH_PROPERTY, info.getProperty(ESCAPE_BACKSLASH_PROPERTY)); 00797 escapeBackProp.required = false; 00798 escapeBackProp.description = ESCAPE_BACKSLASH_PROPERTY_DESCRIPTION; 00799 00800 DriverPropertyInfo escapeSingleProp = new DriverPropertyInfo( 00801 ESCAPE_SINGLE_QUOTE_PROPERTY, info 00802 .getProperty(ESCAPE_SINGLE_QUOTE_PROPERTY)); 00803 escapeSingleProp.required = false; 00804 escapeSingleProp.description = ESCAPE_SINGLE_QUOTE_PROPERTY_DESCRIPTION; 00805 00806 DriverPropertyInfo booleanFalseProp = new DriverPropertyInfo( 00807 BOOLEAN_FALSE_PROPERTY, info.getProperty(BOOLEAN_FALSE_PROPERTY)); 00808 booleanFalseProp.required = false; 00809 booleanFalseProp.description = BOOLEAN_FALSE_PROPERTY_DESCRIPTION; 00810 00811 DriverPropertyInfo booleanTrueProp = new DriverPropertyInfo( 00812 BOOLEAN_TRUE_PROPERTY, info.getProperty(BOOLEAN_TRUE_PROPERTY)); 00813 booleanTrueProp.required = false; 00814 booleanTrueProp.description = BOOLEAN_TRUE_PROPERTY_DESCRIPTION; 00815 00816 DriverPropertyInfo parseQueryProp = new DriverPropertyInfo( 00817 DRIVER_PROCESSED_PROPERTY, info.getProperty(DRIVER_PROCESSED_PROPERTY)); 00818 escapeSingleProp.required = false; 00819 escapeSingleProp.description = DRIVER_PROCESSED_PROPERTY_DESCRIPTION; 00820 00821 return new DriverPropertyInfo[]{hostProp, portProp, databaseProp, userProp, 00822 passwordProp, escapeCharProp, escapeBackProp, escapeSingleProp, 00823 booleanFalseProp, booleanTrueProp, parseQueryProp}; 00824 } 00825 00831 public int getMajorVersion() 00832 { 00833 return MAJOR_VERSION; 00834 } 00835 00841 public int getMinorVersion() 00842 { 00843 return MINOR_VERSION; 00844 } 00845 00856 public boolean jdbcCompliant() 00857 { 00858 return false; 00859 } 00860 00870 private static Character validHostname(String hostname) 00871 { 00872 char[] name = hostname.toCharArray(); 00873 int size = hostname.length(); 00874 char c; 00875 //boolean lastCharWasPoint = false; // used to avoid '..' in hostname 00876 char lastChar = ' '; 00877 00878 for (int i = 0; i < size; i++) 00879 { 00880 c = name[i]; 00881 00882 if (c == '.' || c == '-') 00883 { 00884 if (lastChar == '.' || lastChar == '-' || (i == size - 1) || (i == 0)) 00885 { 00886 // . or - cannot be the first or the last char of hostname 00887 // hostname cannot contain '..' or '.-' or '-.' or '--' 00888 return new Character(c); 00889 } 00890 } 00891 else 00892 { 00893 if (((c < '0') || (c > 'z') || ((c > '9') && (c < 'A')) || ((c > 'Z') && (c < 'a')))) 00894 { 00895 return new Character(c); 00896 } 00897 } 00898 lastChar = c; 00899 } 00900 return null; 00901 } 00902 00912 private static Character validDatabaseName(String databaseName) 00913 { 00914 char[] name = databaseName.toCharArray(); 00915 int size = databaseName.length(); 00916 char c; 00917 00918 for (int i = 0; i < size; i++) 00919 { 00920 c = name[i]; 00921 if ((c < '0') || (c > 'z') || ((c > '9') && (c < 'A')) 00922 || ((c > 'Z') && (c < 'a'))) 00923 return new Character(c); 00924 } 00925 return null; 00926 } 00927 00935 public class ControllerInfo 00936 { 00937 String hostname; 00938 int port; 00939 00943 public ControllerInfo() 00944 { 00945 } 00946 00952 public String getHostname() 00953 { 00954 return hostname; 00955 } 00956 00962 public int getPort() 00963 { 00964 return port; 00965 } 00966 00972 public void setHostname(String string) 00973 { 00974 hostname = string; 00975 } 00976 00982 public void setPort(int port) 00983 { 00984 this.port = port; 00985 } 00986 00990 public String toString() 00991 { 00992 return hostname + ":" + port; 00993 } 00994 } // ControllerInfo class 00995 01001 protected ArrayList getControllerConfig() 01002 { 01003 return controllerConfig; 01004 } 01005 }

CJDBCversion1.0.4に対してTue Oct 12 15:16:05 2004に生成されました。 doxygen 1.3.8