1 21 22 package org.continuent.sequoia.controller.backup.backupers; 23 24 import java.io.File ; 25 import java.io.IOException ; 26 import java.io.InputStream ; 27 import java.sql.Connection ; 28 import java.sql.DriverManager ; 29 import java.sql.Statement ; 30 import java.util.ArrayList ; 31 import java.util.Date ; 32 import java.util.Iterator ; 33 import java.util.regex.Matcher ; 34 import java.util.regex.Pattern ; 35 36 import org.continuent.sequoia.common.exceptions.BackupException; 37 import org.continuent.sequoia.common.log.Trace; 38 import org.continuent.sequoia.controller.backend.DatabaseBackend; 39 40 67 public class MSSQLBackuper extends AbstractBackuper 68 { 69 70 private static final String DEFAULT_MSSQL_PORT = "1433"; 71 private static final String DEFAULT_MSSQL_HOST = "localhost"; 72 private static final String DEFAULT_JDBC_URL = "jdbc:jtds:sqlserver:"; 73 74 private static final Object URL_OPTION = "urlHeader"; 75 private static final Object DRIVER_CLASS_NAME_OPTION = "driverClassName"; 76 77 static Trace logger = Trace 78 .getLogger(MSSQLBackuper.class 79 .getName()); 80 81 private ArrayList errors; 82 83 86 public MSSQLBackuper() 87 { 88 errors = new ArrayList (); 89 } 90 91 94 public String getDumpFormat() 95 { 96 return "MSSQL raw dump"; 97 } 98 99 104 public Date backup(DatabaseBackend backend, String login, String password, 105 String dumpName, String path, ArrayList tables) throws BackupException 106 { 107 String url = backend.getURL(); 108 109 String expectedUrl = (String ) optionsMap.get(URL_OPTION); 110 if (expectedUrl == null) 111 expectedUrl = DEFAULT_JDBC_URL; 112 113 if (!url.startsWith(expectedUrl)) 114 { 115 throw new BackupException("Unsupported db url " + url); 116 } 117 MSSQLUrlInfo info = new MSSQLUrlInfo(url); 118 Connection con; 119 120 try 121 { 122 String driverClassName = (String ) optionsMap 123 .get(DRIVER_CLASS_NAME_OPTION); 124 if (driverClassName == null) 125 driverClassName = backend.getDriverClassName(); 126 127 Class.forName(driverClassName); 129 con = DriverManager.getConnection(url + ";user=" + login + ";password=" 130 + password); 131 } 132 catch (Exception e) 133 { 134 String msg = "Error while performing backup during creation of connection"; 135 logger.error(msg, e); 136 throw new BackupException(msg, e); 137 } 138 139 try 140 { 141 File pathDir = new File (path); 142 if (!pathDir.exists()) 143 { 144 pathDir.mkdirs(); 145 pathDir.mkdir(); 146 } 147 148 153 String dumpPath = path + "\\" + dumpName; 156 157 if (logger.isDebugEnabled()) 158 { 159 logger.debug("Dumping " + backend.getURL() + " in " + dumpPath); 160 } 161 162 Statement stmt = con.createStatement(); 163 String sqlStatement = "BACKUP DATABASE " + info.getDbName() 164 + " TO DISK = '" + dumpPath + "'"; 165 166 logger.debug("sql statement for backup: " + sqlStatement); 167 168 boolean backupResult = stmt.execute(sqlStatement); 169 170 if (backupResult) 171 { 172 String msg = "BACKUP returned false"; 173 logger.error(msg); 174 throw new BackupException(msg); 175 } 176 } 177 catch (Exception e) 178 { 179 String msg = "Error while performing backup"; 180 logger.error(msg, e); 181 throw new BackupException(msg, e); 182 } 183 finally 184 { 185 try 186 { 187 con.close(); 188 } 189 catch (Exception e) 190 { 191 String msg = "Error while performing backup during close connection"; 192 logger.error(msg, e); 193 throw new BackupException(msg, e); 194 } 195 } 196 return new Date (); 197 } 198 199 204 public void restore(DatabaseBackend backend, String login, String password, 205 String dumpName, String path, ArrayList tables) throws BackupException 206 { 207 String url = backend.getURL(); 208 209 String expectedUrl = (String ) optionsMap.get(URL_OPTION); 210 211 if (expectedUrl == null) 212 expectedUrl = DEFAULT_JDBC_URL; 213 214 if (!url.startsWith(expectedUrl)) 215 { 216 throw new BackupException("Unsupported db url " + url); 217 } 218 219 MSSQLUrlInfo info = new MSSQLUrlInfo(url); 220 Connection con; 221 try 222 { 223 String driverClassName = (String ) optionsMap 224 .get(DRIVER_CLASS_NAME_OPTION); 225 if (driverClassName == null) 226 driverClassName = backend.getDriverClassName(); 227 228 Class.forName(driverClassName); 230 231 235 con = DriverManager.getConnection(expectedUrl + "//" + info.getHost() 236 + ":" + info.getPort() + "/master;user=" + login + ";password=" 237 + password); 238 } 239 catch (Exception e) 240 { 241 String msg = "Error while performing restore during creation of connection"; 242 logger.error(msg, e); 243 throw new BackupException(msg, e); 244 } 245 246 try 247 { 248 File pathDir = new File (path); 249 if (!pathDir.exists()) 250 { 251 pathDir.mkdirs(); 252 pathDir.mkdir(); 253 } 254 String dumpPath = path + File.separator + dumpName; 255 if (logger.isDebugEnabled()) 256 { 257 logger.debug("Restoring " + backend.getURL() + " from " + dumpPath); 258 } 259 260 Statement stmt = con.createStatement(); 261 262 String sqlAtatement = "RESTORE DATABASE " + info.getDbName() 263 + " FROM DISK = '" + dumpPath + "'"; 264 265 boolean backupResult = stmt.execute(sqlAtatement); 266 267 if (backupResult) 268 { 269 String msg = "restore returned false"; 270 logger.error(msg); 271 throw new BackupException(msg); 272 } 273 } 274 catch (Exception e) 275 { 276 String msg = "Error while performing restore"; 277 logger.error(msg, e); 278 throw new BackupException(msg, e); 279 } 280 finally 281 { 282 try 283 { 284 con.close(); 285 } 286 catch (Exception e) 287 { 288 String msg = "Error while performing restore during close connection"; 289 logger.error(msg, e); 290 throw new BackupException(msg, e); 291 } 292 } 293 } 294 295 String getProcessOutput(Process process) throws IOException 296 { 297 StringBuffer sb = new StringBuffer (); 298 299 InputStream pis = process.getInputStream(); 300 InputStream pes = process.getErrorStream(); 301 302 int c = pis.read(); 303 while (c != -1) 304 { 305 sb.append(new Character ((char) c)); 306 c = pis.read(); 307 } 308 c = pes.read(); 309 while (c != -1) 310 { 311 sb.append(new Character ((char) c)); 312 c = pes.read(); 313 } 314 315 return sb.toString(); 316 } 317 318 322 public void deleteDump(String path, String dumpName) throws BackupException 323 { 324 File toRemove = new File (getDumpPhysicalPath(path, dumpName)); 325 if (logger.isDebugEnabled()) 326 logger.debug("Deleting compressed dump " + toRemove); 327 toRemove.delete(); 328 } 329 330 337 private String getDumpPhysicalPath(String path, String dumpName) 338 { 339 return path + File.separator + dumpName; 340 } 341 342 345 protected class MSSQLUrlInfo 346 { 347 private boolean isLocal; 348 349 private String host; 350 351 private String port; 352 353 private String dbName; 354 355 362 public MSSQLUrlInfo(String url) 363 { 364 String expectedUrl = (String ) optionsMap.get(URL_OPTION); 365 366 if (expectedUrl == null) 367 expectedUrl = DEFAULT_JDBC_URL; 368 369 Pattern pattern = Pattern 371 .compile(expectedUrl 372 + "((//([a-zA-Z0-9_\\-.]+|\\[[a-fA-F0-9:]+])((:(\\d+))|))/|)([a-zA-Z][a-zA-Z0-9_\\-]*)(\\?.*)?"); 373 374 Matcher matcher; 375 376 matcher = pattern.matcher(url); 377 378 if (matcher.matches()) 379 { 380 if (matcher.group(3) != null) 381 host = matcher.group(3); 382 else 383 host = DEFAULT_MSSQL_HOST; 384 385 if (matcher.group(6) != null) 386 port = matcher.group(6); 387 else 388 port = DEFAULT_MSSQL_PORT; 389 390 dbName = matcher.group(7); 391 } 392 } 393 394 400 public String getHostParametersString() 401 { 402 logger.debug("getHostParamertsString host: " + host + " port: " + port); 403 404 if (isLocal) 405 { 406 return "//localhost"; 407 } 408 else 409 { 410 return "//" + host + ":" + port; 411 } 412 } 413 414 419 public String getDbName() 420 { 421 return dbName; 422 } 423 424 429 public String getHost() 430 { 431 return host; 432 } 433 434 439 public String getPort() 440 { 441 return port; 442 } 443 444 451 public boolean isLocal() 452 { 453 return isLocal; 454 } 455 456 } 457 458 protected void printErrors() 459 { 460 Iterator it = errors.iterator(); 461 while (it.hasNext()) 462 { 463 logger.info(it.next()); 464 } 465 } 466 } 467 | Popular Tags |