1 5 package org.h2.engine; 6 7 import java.sql.SQLException ; 8 import java.util.Arrays ; 9 import java.util.HashSet ; 10 import java.util.Properties ; 11 12 import org.h2.command.dml.SetTypes; 13 import org.h2.message.Message; 14 import org.h2.security.SHA256; 15 import org.h2.util.FileUtils; 16 import org.h2.util.MathUtils; 17 import org.h2.util.ObjectArray; 18 import org.h2.util.StringUtils; 19 20 public class ConnectionInfo { 21 22 private String originalURL; 23 private String url; 24 private Properties prop = new Properties (); 25 private String user; 26 private byte[] filePasswordHash; 27 private byte[] userPasswordHash; 28 private String name; 29 30 private static HashSet KNOWN_SETTINGS = new HashSet (); 31 32 private boolean remote; 33 private boolean ssl; 34 private boolean persistent; 35 36 static { 37 ObjectArray list = SetTypes.getSettings(); 38 for(int i=0; i<list.size(); i++) { 39 KNOWN_SETTINGS.add(list.get(i)); 40 } 41 String [] connectionTime = new String []{ 43 "PASSWORD", "USER", "STORAGE", "FILE_LOCK", "CIPHER", "DB_CLOSE_ON_EXIT", 44 "IGNORE_UNKNOWN_SETTINGS", "IFEXISTS", "RECOVER", "CREATE", "CACHE_TYPE" 45 }; 46 for(int i=0; i<connectionTime.length; i++) { 47 String key = connectionTime[i]; 48 if(Constants.CHECK && KNOWN_SETTINGS.contains(key)) { 49 throw Message.getInternalError(key); 50 } 51 KNOWN_SETTINGS.add(key); 52 } 53 } 54 55 public ConnectionInfo(String name) { 56 this.name = name; 57 parseName(); 58 } 59 60 public ConnectionInfo(String u, Properties info) throws SQLException { 61 this.originalURL = u; 62 this.url = u; 63 readProperties(info); 64 readSettings(); 65 readUser(); 66 readPasswords(); 67 name = url.substring(Constants.START_URL.length()); 68 parseName(); 69 } 70 71 private void parseName() { 72 if(name.equals(".")) { 73 name = "mem:"; 74 } 75 if(name.startsWith("tcp:")) { 76 remote = true; 77 name = name.substring("tcp:".length()); 78 } else if(name.startsWith("ssl:")) { 79 remote = true; 80 ssl = true; 81 name = name.substring("ssl:".length()); 82 } else if(name.startsWith("mem:")) { 83 persistent = false; 84 } else if(name.startsWith("file:")) { 85 name = name.substring("file:".length()); 86 persistent = true; 87 } else { 88 persistent = true; 89 } 90 } 91 92 public String getDatabaseName() { 93 if(remote) { 94 if(ssl) { 95 return "ssl:" + name; 96 } else { 97 return "tcp:" + name; 98 } 99 } else if(persistent) { 100 return "file:" + name; 101 } 102 return name; 103 } 104 105 public void setBaseDir(String dir) { 106 if(persistent) { 107 name = dir + System.getProperty("file.separator") + name; 108 } 109 } 110 111 public boolean isRemote() { 112 return remote; 113 } 114 115 public boolean isPersistent() { 116 return persistent; 117 } 118 119 private void readProperties(Properties info) throws SQLException { 120 Object [] list = new Object [info.size()]; 121 info.keySet().toArray(list); 122 for(int i=0; i<list.length; i++) { 123 String key = StringUtils.toUpperEnglish(list[i].toString()); 124 if(prop.containsKey(key)) { 125 throw Message.getSQLException(Message.DUPLICATE_PROPERTY_1, key); 126 } 127 if(KNOWN_SETTINGS.contains(key)) { 128 prop.put(key, info.get(list[i])); 129 } 130 } 131 } 132 133 private void readSettings() throws SQLException { 134 int idx = url.indexOf(';'); 135 if(idx >= 0) { 136 String settings = url.substring(idx + 1); 137 url = url.substring(0, idx); 138 String [] list = StringUtils.arraySplit(settings, ';', false); 139 for(int i=0; i<list.length; i++) { 140 String setting = list[i]; 141 int equal = setting.indexOf('='); 142 if(equal < 0) { 143 throw getFormatException(); 144 } 145 String value = setting.substring(equal+1); 146 String key = setting.substring(0, equal); 147 key = StringUtils.toUpperEnglish(key); 148 if(!KNOWN_SETTINGS.contains(key)) { 149 throw Message.getSQLException(Message.UNSUPPORTED_SETTING_1, key); 150 } 151 String old = prop.getProperty(key); 152 if(old != null && !old.equals(value)) { 153 throw Message.getSQLException(Message.DUPLICATE_PROPERTY_1, key); 154 } 155 prop.setProperty(key, value); 156 } 157 } 158 } 159 160 private char[] removePassword() { 161 Object p = prop.remove("PASSWORD"); 162 if(p == null) { 163 return new char[0]; 164 } else if(p instanceof char[]) { 165 return (char[])p; 166 } else { 167 return p.toString().toCharArray(); 168 } 169 } 170 171 private void readUser() { 172 user = StringUtils.toUpperEnglish(removeProperty("USER", "")); 174 } 175 176 void readPasswords() throws SQLException { 177 char[] password = removePassword(); 178 SHA256 sha = new SHA256(); 179 if(getProperty("CIPHER", null) != null) { 180 int space = -1; 182 for(int i=0; i<password.length;i++) { 183 if(password[i] == ' ') { 184 space = i; 185 break; 186 } 187 } 188 if(space < 0) { 189 throw Message.getSQLException(Message.WRONG_PASSWORD_FORMAT); 190 } 191 char[] np = new char[password.length - space -1]; 192 char[] filePassword = new char[space]; 193 System.arraycopy(password, space+1, np, 0, np.length); 194 System.arraycopy(password, 0, filePassword, 0, space); 195 Arrays.fill(password, (char)0); 196 password = np; 197 filePasswordHash = sha.getKeyPasswordHash("file", filePassword); 198 } 199 userPasswordHash = sha.getKeyPasswordHash(user, password); 200 } 201 202 public boolean removeProperty(String key, boolean defaultValue) { 203 String x = removeProperty(key, null); 204 return x == null ? defaultValue : Boolean.valueOf(x).booleanValue(); 205 } 206 207 public String removeProperty(String key, String defaultValue) { 208 if(Constants.CHECK && !KNOWN_SETTINGS.contains(key)) { 209 throw Message.getInternalError(key); 210 } 211 Object x = prop.remove(key); 212 return x == null ? defaultValue : x.toString(); 213 } 214 215 public String getName() throws SQLException { 216 if(persistent) { 217 String n = FileUtils.normalize(name + Constants.SUFFIX_DATA_FILE); 218 n = n.substring(0, n.length() - Constants.SUFFIX_DATA_FILE.length()); 219 return FileUtils.normalize(n); 220 } 221 return name; 222 } 223 224 public byte[] getFilePasswordHash() { 225 return filePasswordHash; 226 } 227 228 public String getUserName() { 229 return user; 230 } 231 232 public byte[] getUserPasswordHash() { 233 return userPasswordHash; 234 } 235 236 public String [] getKeys() { 237 String [] keys = new String [prop.size()]; 238 prop.keySet().toArray(keys); 239 return keys; 240 } 241 242 public String getProperty(String key) { 243 return prop.getProperty(key); 244 } 245 246 public String getProperty(String key, String defaultValue) { 247 if(Constants.CHECK && !KNOWN_SETTINGS.contains(key)) { 248 throw Message.getInternalError(key); 249 } 250 String s = getProperty(key); 251 return s == null ? defaultValue : s; 252 } 253 254 public String getProperty(int setting, String defaultValue) { 255 String key = SetTypes.getTypeName(setting); 256 String s = getProperty(key); 257 return s == null ? defaultValue : s; 258 } 259 260 public int getIntProperty(int setting, int defaultValue) { 261 String key = SetTypes.getTypeName(setting); 262 String s = getProperty(key, null); 263 try { 264 return s == null ? defaultValue : MathUtils.decodeInt(s); 265 } catch(NumberFormatException e) { 266 return defaultValue; 267 } 268 } 269 270 public boolean isSSL() { 271 return ssl; 272 } 273 274 public void setUserName(String name) { 275 this.user = name; 276 } 277 278 public void setUserPasswordHash(byte[] bs) { 279 this.userPasswordHash = bs; 280 } 281 282 public void setFilePasswordHash(byte[] bs) { 283 this.filePasswordHash = bs; 284 } 285 286 public void setProperty(String key, String value) { 287 prop.setProperty(key, value); 288 } 289 290 public String getURL() { 291 return url; 292 } 293 294 public String getOriginalURL() { 295 return originalURL; 296 } 297 298 public void setOriginalURL(String url) { 299 originalURL = url; 300 } 301 302 boolean getTextStorage() throws SQLException { 303 String storage = removeProperty("STORAGE", "BINARY"); 304 if("BINARY".equalsIgnoreCase(storage)) { 305 return false; 306 } else if("TEXT".equalsIgnoreCase(storage)) { 307 return true; 308 } else { 309 throw Message.getInvalidValueException(storage, "storage"); 310 } 311 } 312 313 public SQLException getFormatException() { 314 String format = Constants.URL_FORMAT; 315 return Message.getSQLException(Message.URL_FORMAT_ERROR_2, new String []{format, url}, null); 316 } 317 318 } 319 | Popular Tags |