1 23 24 package org.objectweb.cjdbc.driver; 25 26 import java.sql.SQLException ; 27 import java.util.HashMap ; 28 import java.util.StringTokenizer ; 29 30 import org.objectweb.cjdbc.controller.core.ControllerConstants; 31 import org.objectweb.cjdbc.driver.connectpolicy.AbstractControllerConnectPolicy; 32 import org.objectweb.cjdbc.driver.connectpolicy.OrderedConnectPolicy; 33 import org.objectweb.cjdbc.driver.connectpolicy.PreferredListConnectPolicy; 34 import org.objectweb.cjdbc.driver.connectpolicy.RandomConnectPolicy; 35 import org.objectweb.cjdbc.driver.connectpolicy.RoundRobinConnectPolicy; 36 import org.objectweb.cjdbc.driver.connectpolicy.SingleConnectPolicy; 37 38 47 public class CjdbcUrl 48 { 49 private String url; 50 private String databaseName; 51 private ControllerInfo[] controllerList; 52 private HashMap parameters; 53 private AbstractControllerConnectPolicy controllerConnectPolicy; 54 55 private int debugLevel; 57 58 public static final int DEBUG_LEVEL_DEBUG = 2; 59 60 public static final int DEBUG_LEVEL_INFO = 1; 61 62 public static final int DEBUG_LEVEL_OFF = 0; 63 64 71 public CjdbcUrl(String url) throws SQLException 72 { 73 this.url = url; 74 parseUrl(); 75 String debugProperty = (String ) parameters.get(Driver.DEBUG_PROPERTY); 76 debugLevel = DEBUG_LEVEL_OFF; 77 if (debugProperty != null) 78 { 79 if ("debug".equals(debugProperty)) 80 debugLevel = DEBUG_LEVEL_DEBUG; 81 else if ("info".equals(debugProperty)) 82 debugLevel = DEBUG_LEVEL_INFO; 83 } 84 controllerConnectPolicy = createConnectionPolicy(); 85 } 86 87 92 public boolean isDebugEnabled() 93 { 94 return debugLevel == DEBUG_LEVEL_DEBUG; 95 } 96 97 102 public boolean isInfoEnabled() 103 { 104 return debugLevel >= DEBUG_LEVEL_INFO; 105 } 106 107 112 public AbstractControllerConnectPolicy getControllerConnectPolicy() 113 { 114 return controllerConnectPolicy; 115 } 116 117 122 public ControllerInfo[] getControllerList() 123 { 124 return controllerList; 125 } 126 127 132 public String getDatabaseName() 133 { 134 return databaseName; 135 } 136 137 145 public HashMap getParameters() 146 { 147 return parameters; 148 } 149 150 155 public String getUrl() 156 { 157 return url; 158 } 159 160 165 public void setUrl(String url) 166 { 167 this.url = url; 168 } 169 170 174 181 private AbstractControllerConnectPolicy createConnectionPolicy() 182 { 183 if (controllerList.length == 1) 184 return new SingleConnectPolicy(controllerList, debugLevel); 185 186 String policy = (String ) parameters 187 .get(Driver.PREFERRED_CONTROLLER_PROPERTY); 188 String retryInterval = (String ) parameters 189 .get(Driver.RETRY_INTERVAL_IN_MS_PROPERTY); 190 long retryIntervalInMs; 191 192 if (retryInterval == null) 194 retryIntervalInMs = Driver.DEFAULT_RETRY_INTERVAL_IN_MS; 195 else 196 retryIntervalInMs = Long.parseLong(retryInterval); 197 198 if (policy == null) 199 return new RandomConnectPolicy(controllerList, retryIntervalInMs, 200 debugLevel); 201 202 if (policy.equals("roundRobin")) 207 return new RoundRobinConnectPolicy(controllerList, retryIntervalInMs, 208 debugLevel); 209 210 if (policy.equals("ordered")) 214 return new OrderedConnectPolicy(controllerList, retryIntervalInMs, 215 debugLevel); 216 217 if (policy.equals("random")) 220 return new RandomConnectPolicy(controllerList, retryIntervalInMs, 221 debugLevel); 222 223 return new PreferredListConnectPolicy(controllerList, retryIntervalInMs, 226 policy, debugLevel); 227 } 228 229 235 private void parseUrl() throws SQLException 236 { 237 if (url == null) 239 { 240 throw new IllegalArgumentException ( 241 "Illegal null URL in parseURL(String) method"); 242 } 243 244 if (!url.toLowerCase().startsWith(Driver.CJDBC_URL_HEADER)) 245 throw new SQLException ("Malformed header from URL '" + url 246 + "' (expected '" + Driver.CJDBC_URL_HEADER + "')"); 247 else 248 { 249 int nextSlash = url.indexOf('/', Driver.CJDBC_URL_HEADER_LENGTH); 251 if (nextSlash == -1) 252 throw new SQLException ("Malformed URL '" + url + "' (expected '" 254 + Driver.CJDBC_URL_HEADER + "<hostname>/<database>')"); 255 256 int questionMark = url.indexOf('?', nextSlash); 258 questionMark = (questionMark == -1) 259 ? url.indexOf(';', nextSlash) 260 : questionMark; 261 262 String controllerURLs = url.substring(Driver.CJDBC_URL_HEADER_LENGTH, 263 nextSlash); 264 StringTokenizer controllers = new StringTokenizer (controllerURLs, ",", 267 false); 268 int tokenNumber = controllers.countTokens(); 269 if (tokenNumber == 0) 270 { 271 throw new SQLException ("Empty controller name in '" + controllerURLs 272 + "' in URL '" + url + "'"); 273 } 274 controllerList = new ControllerInfo[tokenNumber]; 275 int i = 0; 276 String token; 277 while (controllers.hasMoreTokens()) 280 { 281 token = controllers.nextToken().trim(); 282 if (token.equals("")) { 284 throw new SQLException ("Empty controller name in '" + controllerURLs 285 + "' in URL '" + url + "'"); 286 } 287 controllerList[i] = parseController(token); 288 i++; 289 } 290 291 databaseName = (questionMark == -1) ? url.substring(nextSlash + 1, url 293 .length()) : url.substring(nextSlash + 1, questionMark); 294 Character c = validDatabaseName(databaseName); 295 if (c != null) 296 throw new SQLException ( 297 "Unable to validate database name (unacceptable character '" + c 298 + "' in database '" + databaseName + "' from URL '" + url 299 + "')"); 300 301 parameters = parseUrlParams(url); 303 } 304 } 305 306 314 private HashMap parseUrlParams(String urlString) throws SQLException 315 { 316 HashMap props = parseUrlParams(urlString, '?', "&", "="); 317 if (props == null) 318 props = parseUrlParams(urlString, ';', ";", "="); 319 if (props == null) 320 props = new HashMap (); 321 322 return props; 323 } 324 325 337 private HashMap parseUrlParams(String urlString, char beginMarker, 338 String parameterSeparator, String equal) throws SQLException 339 { 340 int questionMark = urlString.indexOf(beginMarker, urlString 341 .lastIndexOf('/')); 342 if (questionMark == -1) 343 return null; 344 else 345 { 346 HashMap props = new HashMap (); 347 String params = urlString.substring(questionMark + 1); 348 StringTokenizer st1 = new StringTokenizer (params, parameterSeparator); 349 while (st1.hasMoreTokens()) 350 { 351 String param = st1.nextToken(); 352 StringTokenizer st2 = new StringTokenizer (param, equal); 353 if (st2.hasMoreTokens()) 354 { 355 try 356 { 357 String paramName = st2.nextToken(); 358 String paramValue = (st2.hasMoreTokens()) ? st2.nextToken() : ""; 359 props.put(paramName, paramValue); 360 } 361 catch (Exception e) { 363 throw new SQLException ("Invalid parameter in URL: " + urlString); 364 } 365 } 366 } 367 return props; 368 } 369 } 370 371 379 public static ControllerInfo parseController(String controller) 380 throws SQLException 381 { 382 ControllerInfo controllerInfo = new ControllerInfo(); 383 384 StringTokenizer controllerURL = new StringTokenizer (controller, ":", true); 386 387 controllerInfo.setHostname(controllerURL.nextToken()); 389 Character c = validHostname(controllerInfo.getHostname()); 390 if (c != null) 391 throw new SQLException ( 392 "Unable to validate hostname (unacceptable character '" + c 393 + "' in hostname '" + controllerInfo.getHostname() 394 + "' from the URL part '" + controller + "')"); 395 396 if (!controllerURL.hasMoreTokens()) 397 controllerInfo.setPort(ControllerConstants.DEFAULT_PORT); 398 else 399 { 400 controllerURL.nextToken(); if (!controllerURL.hasMoreTokens()) 402 controllerInfo.setPort(ControllerConstants.DEFAULT_PORT); 403 else 404 { String port = controllerURL.nextToken(); 406 if (controllerURL.hasMoreTokens()) 407 throw new SQLException ( 408 "Invalid controller definition with more than one semicolon in URL part '" 409 + controller + "'"); 410 411 try 413 { 414 controllerInfo.setPort(Integer.parseInt(port)); 415 } 416 catch (NumberFormatException ne) 417 { 418 throw new SQLException ( 419 "Unable to validate port number (unacceptable port number '" 420 + port + "' in this URL part '" + controller + "')"); 421 } 422 } 423 } 424 return controllerInfo; 425 } 426 427 436 private static Character validHostname(String hostname) 437 { 438 char[] name = hostname.toCharArray(); 439 int size = hostname.length(); 440 char c; 441 char lastChar = ' '; 443 444 for (int i = 0; i < size; i++) 445 { 446 c = name[i]; 447 448 if (c == '.' || c == '-') 449 { 450 if (lastChar == '.' || lastChar == '-' || (i == size - 1) || (i == 0)) 451 { 452 return new Character (c); 455 } 456 } 457 else 458 { 459 if (((c < '0') || (c > 'z') || ((c > '9') && (c < 'A')) 460 || ((c > 'Z') && (c < '_')) || (c == '`'))) 461 { 462 return new Character (c); 463 } 464 } 465 lastChar = c; 466 } 467 return null; 468 } 469 470 479 private static Character validDatabaseName(String databaseName) 480 { 481 char[] name = databaseName.toCharArray(); 482 int size = databaseName.length(); 483 char c; 484 485 for (int i = 0; i < size; i++) 486 { 487 c = name[i]; 488 if ((c < '-') || (c > 'z') || (c == '/') || (c == '.') || (c == '`') 489 || ((c > '9') && (c < 'A')) || ((c > 'Z') && (c < '_'))) 490 return new Character (c); 491 } 492 return null; 493 } 494 } 495 | Popular Tags |