1 23 24 package org.continuent.sequoia.controller.backup.backupers; 25 26 import java.io.BufferedReader ; 27 import java.io.BufferedWriter ; 28 import java.io.File ; 29 import java.io.FileNotFoundException ; 30 import java.io.FileReader ; 31 import java.io.FileWriter ; 32 import java.io.IOException ; 33 import java.io.PrintStream ; 34 import java.util.ArrayList ; 35 import java.util.Date ; 36 import java.util.Hashtable ; 37 import java.util.Iterator ; 38 39 import org.apache.log4j.Category; 40 import org.apache.log4j.Priority; 41 import org.continuent.sequoia.common.exceptions.BackupException; 42 import org.continuent.sequoia.common.exceptions.OctopusException; 43 import org.continuent.sequoia.common.i18n.Translate; 44 import org.continuent.sequoia.common.log.Trace; 45 import org.continuent.sequoia.common.util.FileManagement; 46 import org.continuent.sequoia.common.util.LoggingOutputStream; 47 import org.continuent.sequoia.controller.backend.DatabaseBackend; 48 import org.continuent.sequoia.controller.backup.DumpTransferInfo; 49 import org.continuent.sequoia.controller.sql.schema.DatabaseTable; 50 import org.webdocwf.util.loader.Loader; 51 import org.webdocwf.util.loader.generator.LoaderGenerator; 52 53 71 public class OctopusBackuper extends AbstractBackuper 72 { 73 static Trace logger = Trace 74 .getLogger(OctopusBackuper.class 75 .getName()); 76 private boolean redirectOutput = false; 77 private boolean zipBackupFiles = true; 78 79 static 80 { 81 String sequoiaHome = System.getProperty("sequoia.home"); 82 if (sequoiaHome != null) 83 System.setProperty("OCTOPUS_HOME", sequoiaHome + File.separator + "lib" 84 + File.separator + "octopus" + File.separator + "xml"); 85 } 86 87 91 private static final int DB_NAME = 0; 92 private static final int DRIVER = 1; 93 private static final int FULL_NAME = 2; 94 private static final int PREFIX_URL = 3; 95 96 103 private static final String [] HSQL = {"hsqldb", "hsql", 104 "HypersonicSQL", "jdbc:hsqldb:" }; 105 private static final String [] CSV = {"csv", "csv", "Csv", 106 "jdbc:relique:csv:" }; 107 private static final String [] MYSQL = {"mysql", "mm", "MySQL", 108 "jdbc:mysql://" }; 109 private static final String [] POSTGRESQL = {"postgresql", "postgresql", 110 "PostgreSQL", "jdbc:postgresql://" }; 111 private static final String [] ORACLE = {"oracle", "oracle", "Oracle", 112 "jdbc:oracle:thin:" }; 113 private static final String [] JTURBO = {"jTurbo", "jTurbo", "MSQL", 114 "jdbc:JTurbo://" }; 115 private static final String [] MSSQL = {"microsoft", "microsoft", 116 "MSQL", "jdbc:microsoft:sqlserver://" }; 117 118 static final Hashtable TYPES; 119 static 120 { 121 TYPES = new Hashtable (); 122 TYPES.put(HSQL[DB_NAME], HSQL); 123 TYPES.put(CSV[DB_NAME], CSV); 124 TYPES.put(MYSQL[DB_NAME], MYSQL); 125 TYPES.put(ORACLE[DB_NAME], ORACLE); 126 TYPES.put(POSTGRESQL[DB_NAME], POSTGRESQL); 127 TYPES.put(JTURBO[DB_NAME], JTURBO); 128 TYPES.put(MSSQL[DB_NAME], MSSQL); 129 } 130 131 135 138 public OctopusBackuper() 139 { 140 } 141 142 145 public String getDumpFormat() 146 { 147 if (zipBackupFiles) 148 return "Octopus v3.4.1 database neutral dump compressed"; 149 else 150 return "Octopus v3.4.1 database neutral dump"; 151 } 152 153 158 public Date backup(DatabaseBackend backend, String login, String password, 159 String dumpName, String path, ArrayList tables) throws BackupException 160 { 161 logger.info(Translate.get("backup.manager.backuping.backend", new String []{ 162 backend.getName(), dumpName})); 163 164 if (logger.isDebugEnabled()) 165 logger.debug("Creating directory for backup"); 166 167 String octopusDir = createOctopusDir(path, dumpName); 169 170 String type = getDatabaseType(backend.getURL()); 171 String sourceType = getOctopusType(type); 172 String sourceUrl = backend.getURL().substring(getUrlPrefix(type).length()); 173 String sourceDriver = getOctopusDriver(type); 174 String targetType = getOctopusType(TYPE_CSV); 175 String targetDriver = getOctopusDriver(TYPE_CSV); 176 String targetUrl = createCsvDir(octopusDir); 177 String targetUser = ""; 178 String targetPassword = ""; 179 180 PrintStream oldStream = null; 181 if (redirectOutput) 182 { 183 if (logger.isDebugEnabled()) 184 logger.debug("Redirecting Octopus output streams"); 185 186 oldStream = redirectOutputStream(); 188 } 189 190 try 191 { 192 if (logger.isDebugEnabled()) 194 logger.debug("### Generating Octopus metadata ###"); 195 callOctopusLoader(sourceType, sourceUrl, sourceDriver, login, password, 196 targetType, targetDriver, targetUrl, targetUser, targetPassword, 197 true, true, octopusDir); 198 199 if (logger.isDebugEnabled()) 201 logger.debug("### Generating loader job ###"); 202 callOctopusLoader(sourceType, sourceUrl, sourceDriver, login, password, 203 targetType, targetDriver, targetUrl, targetUser, targetPassword, 204 true, false, octopusDir); 205 206 if (logger.isDebugEnabled()) 207 { 208 logger.debug("======================================="); 209 logger.debug("Using the following Octopus settings:"); 210 logger.debug("Octopus dump directory=" + octopusDir); 211 logger.debug("Target URL=" + targetUrl); 212 logger.debug("Loader job file=" + getLoaderJobFile(octopusDir)); 213 logger.debug("Compress backup=" + zipBackupFiles); 214 logger.debug("OCTOPUS HOME:" + System.getProperty("OCTOPUS_HOME")); 215 logger.debug("======================================="); 216 } 217 218 launchOctopus(octopusDir, dumpName, tables); 220 221 if (redirectOutput) 222 { 223 System.setOut(oldStream); 225 } 226 } 227 catch (Exception e) 228 { 229 if (redirectOutput) 230 { 231 System.setOut(oldStream); 233 } 234 String msg = "Error while performing backup for backend " 235 + backend.getName(); 236 logger.error(msg, e); 237 throw new BackupException(msg, e); 238 } 239 240 if (zipBackupFiles) 242 { 243 try 244 { 245 if (logger.isDebugEnabled()) 246 logger.debug("Compressing dump"); 247 Zipper.zip(path + File.separator + dumpName + Zipper.ZIP_EXT, 248 octopusDir, Zipper.STORE_PATH_FROM_ZIP_ROOT); 249 if (logger.isDebugEnabled()) 250 logger.debug("Cleaning uncompressed dump files"); 251 cleanUp(octopusDir); 252 } 253 catch (Exception e) 254 { 255 String msg = "Error while compressing dump"; 256 logger.error(msg, e); 257 throw new BackupException(msg, e); 258 } 259 } 260 261 return new Date (System.currentTimeMillis()); 262 } 263 264 269 public void restore(DatabaseBackend backend, String login, String password, 270 String dumpName, String path, ArrayList tables) throws BackupException 271 { 272 logger.info(Translate.get("backup.manager.restoring.backend", new String []{ 273 backend.getName(), dumpName})); 274 275 String octopusDir = createOctopusDir(path, dumpName); 277 278 if (zipBackupFiles) 279 { 280 try 281 { 282 if (logger.isDebugEnabled()) 283 logger.debug("Uncompressing dump"); 284 Zipper.unzip(path + File.separator + dumpName + Zipper.ZIP_EXT, 285 octopusDir); 286 } 287 catch (Exception e) 288 { 289 String msg = "Error while uncompressing dump"; 290 logger.error(msg, e); 291 throw new BackupException(msg, e); 292 } 293 } 294 295 String type = getDatabaseType(backend.getURL()); 296 String targetType = getOctopusType(type); 297 String targetUrl = backend.getURL().substring(getUrlPrefix(type).length()); 298 String targetDriver = getOctopusDriver(type); 299 String sourceType = getOctopusType(TYPE_CSV); 300 String sourceDriver = getOctopusDriver(TYPE_CSV); 301 String sourceUrl = createCsvDir(octopusDir); 302 String sourceUser = ""; 303 String sourcePassword = ""; 304 305 PrintStream oldStream = null; 306 if (redirectOutput) 307 { 308 if (logger.isDebugEnabled()) 309 logger.debug("Redirecting Octopus output streams"); 310 311 oldStream = redirectOutputStream(); 313 } 314 315 try 316 { 317 if (logger.isDebugEnabled()) 319 logger.debug("### Generating loader job ###"); 320 callOctopusLoader(sourceType, sourceUrl, sourceDriver, sourceUser, 321 sourcePassword, targetType, targetDriver, targetUrl, login, password, 322 false, false, octopusDir); 323 324 setOctopusLoaderJob(octopusDir, sourceType); 325 326 if (logger.isDebugEnabled()) 327 { 328 logger.debug("======================================="); 329 logger.debug("Using the following Octopus settings:"); 330 logger.debug("Octopus dump directory=" + octopusDir); 331 logger.debug("Source URL=" + sourceUrl); 332 logger.debug("Target URL=" + targetUrl); 333 logger.debug("Loader job file=" + getLoaderJobFile(octopusDir)); 334 logger.debug("Compress backup=" + zipBackupFiles); 335 logger.debug("OCTOPUS HOME:" + System.getProperty("OCTOPUS_HOME")); 336 logger.debug("======================================="); 337 } 338 339 launchOctopus(octopusDir, dumpName, tables); 341 342 if (zipBackupFiles) 343 { 344 if (logger.isDebugEnabled()) 345 logger.debug("Cleaning backup files"); 346 cleanUp(octopusDir); 347 } 348 349 if (redirectOutput) 350 { 351 System.setOut(oldStream); 353 } 354 } 355 catch (Exception e) 356 { 357 if (redirectOutput) 358 { 359 System.setOut(oldStream); 361 } 362 String msg = "Error while performing restore operation on backend " 363 + backend.getName(); 364 logger.error(msg, e); 365 throw new BackupException(msg, e); 366 } 367 } 368 369 373 public void deleteDump(String path, String dumpName) throws BackupException 374 { 375 if (zipBackupFiles) 376 { 377 File toRemove = new File (path + File.separator + dumpName 378 + Zipper.ZIP_EXT); 379 if (logger.isDebugEnabled()) 380 logger.debug("Deleting compressed dump " + toRemove); 381 toRemove.delete(); 382 } 383 else 384 { 385 if (logger.isDebugEnabled()) 386 logger.debug("Deleting dump directory " + path + File.separator 387 + dumpName); 388 cleanUp(path + File.separator + dumpName); 389 } 390 } 391 392 396 private static final String TYPE_CSV = "csv"; 397 private static final String COPY_MODE = "copy"; 398 private static final String OCTOPUS_INCLUDE_HREF = "<include HREF=\"sql/"; 399 400 private void callOctopusLoader(String sourceType, String sourceUrl, 401 String sourceDriver, String sourceUser, String sourcePassword, 402 String targetType, String targetDriver, String targetUrl, 403 String targetUser, String targetPassword, boolean backup, 404 boolean generateAllVendors, String octopusDir) throws OctopusException 405 { 406 try 407 { 408 if (logger.isDebugEnabled()) 409 { 410 logger.debug("Source Type:" + sourceType); 411 logger.debug("Source Driver:" + sourceDriver); 412 logger.debug("Source URL :" + sourceUrl); 413 logger.debug("Source User :" + sourceUser); 414 logger.debug("Target Type:" + targetType); 415 logger.debug("Target Driver:" + targetDriver); 416 logger.debug("Target URL:" + targetUrl); 417 logger.debug("Target User :" + targetUser); 418 logger.debug("Generate SQL for all vendors :" + generateAllVendors); 419 } 420 LoaderGenerator loader = new LoaderGenerator(sourceType, sourceUrl, COPY_MODE, octopusDir, sourceDriver, targetDriver, targetUrl, targetType, sourceUser, sourcePassword, targetUser, targetPassword, "", "org.webdoc.util.loader", "true", "true", "true", "true", "true", "true", String.valueOf(generateAllVendors), String.valueOf(!generateAllVendors), "false", String.valueOf(!generateAllVendors), String.valueOf(!backup), null, null ); 449 loader.generate(); 450 } 451 catch (Exception e) 452 { 453 throw new OctopusException(e); 454 } 455 } 456 457 464 private void launchOctopus(String octopusDir, String dumpName, 465 ArrayList tables) throws OctopusException 466 { 467 try 468 { 469 Loader myOctopus; 470 String loaderLogging; 471 if (logger.isDebugEnabled()) 472 loaderLogging = Loader.LOGMODE_FULL; 473 else if (!logger.isFatalEnabled()) loaderLogging = Loader.LOGMODE_NONE; 475 else 476 loaderLogging = Loader.LOGMODE_NORMAL; 477 478 if (tables == null) 479 { 480 myOctopus = new Loader(getLoaderJobFile(octopusDir), loaderLogging, 482 "sequoia", octopusDir, "Octopus" + dumpName + ".log", true, null, 483 null, true, null, 0, 100); 484 } 485 else 486 { 487 myOctopus = new Loader(getLoaderJobFile(octopusDir), loaderLogging, 489 "sequoia", octopusDir, "Octopus" + dumpName + ".log", true, null, 490 null, true, null, 0, 100, convertTablesToArray(tables)); 491 } 492 try 493 { 494 myOctopus.load(); 495 } 496 catch (Exception e) 497 { 498 logger.error("Failed to load octopus", e); 499 throw new OctopusException(Translate.get( 500 "controller.octopus.load.failed", e)); 501 } 502 } 503 catch (OctopusException oe) 506 { 507 throw oe; 509 } 510 catch (Exception e) 511 { 512 throw new OctopusException(Translate 513 .get("controller.octopus.instance.failed")); 514 } 515 } 516 517 private void cleanUp(String octopusDir) 518 { 519 if (logger.isDebugEnabled()) 520 logger.debug("Cleaning up temporary backup files..."); 521 File toRemove = new File (octopusDir); 522 FileManagement.deleteDir(toRemove); 523 } 524 525 private String [] convertTablesToArray(ArrayList tablesList) 526 { 527 int length = tablesList.size(); 528 String [] result = new String [length]; 529 for (int i = 0; i < length; i++) 530 result[i] = ((DatabaseTable) tablesList.get(i)).getName(); 531 return result; 532 } 533 534 private String createOctopusDir(String path, String dumpName) 535 throws BackupException 536 { 537 String octopusDir = path + File.separator + dumpName; 539 540 File octopusd = new File (octopusDir); 541 octopusd.mkdirs(); 542 octopusd.mkdir(); 543 544 if (!octopusd.exists()) 545 throw new BackupException("backup.directory.cannot.be.created"); 546 547 return octopusDir; 548 } 549 550 private String createCsvDir(String octopusDir) throws BackupException 551 { 552 String csvDir = TYPE_CSV; 554 File csvd = new File (octopusDir + File.separator + csvDir); 555 csvDir = csvd.getAbsolutePath(); 556 csvd.mkdirs(); 557 csvd.mkdir(); 558 559 if (!csvd.exists()) 560 throw new BackupException("backup.directory.cannot.be.created"); 561 562 return csvDir; 563 } 564 565 private String getDatabaseType(String url) throws BackupException 566 { 567 if (url == null) 568 throw new BackupException("Invalid null source url"); 569 int index = url.indexOf(':'); 570 int index2 = url.indexOf(':', index + 1); 571 if (index == -1 || index2 == -1 || index > index2) 572 throw new BackupException("Invalid source url format"); 573 String type = url.substring(index + 1, index2); 574 return type; 575 } 576 577 private String getLoaderJobFile(String octopusDir) 578 { 579 return octopusDir + File.separator + "LoaderJob.olj"; 580 } 581 582 private PrintStream redirectOutputStream() 583 { 584 PrintStream previousOut = System.out; 585 System.setOut(new PrintStream (new LoggingOutputStream(Category 586 .getInstance(this.getClass().getName()), Priority.DEBUG), true)); 587 return previousOut; 588 } 589 590 private void setOctopusLoaderJob(String octopusDir, String sourceType) 591 throws OctopusException 592 { 593 String onErrorContinueEqualFalse = "onErrorContinue=\"false\""; 594 String onErrorContinueEqualTrue = "onErrorContinue=\"true\""; 595 BufferedReader br = null; 596 BufferedWriter bw = null; 597 598 try 599 { 600 br = new BufferedReader (new FileReader (getLoaderJobFile(octopusDir))); 601 String line = ""; 602 StringBuffer buffer = new StringBuffer (); 603 604 while ((line = br.readLine()) != null) 605 { 606 607 int idx = line.indexOf(OCTOPUS_INCLUDE_HREF); 608 if (idx != -1) 609 { 610 idx += OCTOPUS_INCLUDE_HREF.length(); 611 line = line.substring(0, idx - 4) + ".." + File.separator 613 + octopusDir + File.separator + "SQLForAllVendors" 614 + File.separator + sourceType + File.separator + "sql" 615 + File.separator + line.substring(idx); 616 } 617 618 619 int index7 = line.indexOf(onErrorContinueEqualFalse); 620 if (index7 != -1) 621 { 622 line = line.substring(0, index7) + onErrorContinueEqualTrue 623 + line.substring(index7 + onErrorContinueEqualFalse.length()); 624 } 625 buffer.append(line + System.getProperty("line.separator")); 626 } 627 br.close(); 628 if (logger.isDebugEnabled()) 629 { 630 logger.debug("Octopus file updated with success"); 631 } 632 633 bw = new BufferedWriter (new FileWriter (getLoaderJobFile(octopusDir))); 634 bw.write(buffer.toString()); 635 bw.close(); 636 } 637 catch (FileNotFoundException fie) 638 { 639 logger.warn(Translate.get("controller.octopus.loader.job.not.found")); 641 throw new OctopusException(fie.getMessage()); 642 } 643 catch (IOException e) 644 { 645 logger.warn(Translate.get("controller.octopus.loader.io.problem")); 647 } 648 finally 649 { 650 if (bw != null) 652 try 653 { 654 bw.close(); 655 } 656 catch (IOException e1) 657 { 658 659 } 660 if (br != null) 661 try 662 { 663 br.close(); 664 } 665 catch (IOException e2) 666 { 667 } 668 } 669 } 670 671 678 private String getOctopusType(String type) throws BackupException 679 { 680 if (type == null) 681 return null; 682 683 if (!TYPES.containsKey(type)) 685 throw new BackupException( 686 "OctopusBackuper does not support this database type."); 687 688 return ((String []) TYPES.get(type))[OctopusBackuper.FULL_NAME]; 689 } 690 691 697 private String getOctopusDriver(String type) 698 { 699 if (type == null) 700 return null; 701 return ((String []) TYPES.get(type))[OctopusBackuper.DRIVER]; 702 } 703 704 710 private String getUrlPrefix(String type) 711 { 712 if (type == null) 713 return null; 714 return ((String []) TYPES.get(type))[OctopusBackuper.PREFIX_URL]; 715 } 716 717 721 724 public void setOptions(String options) 725 { 726 super.setOptions(options); 727 728 for (Iterator iter = optionsMap.keySet().iterator(); iter.hasNext();) 729 { 730 String option = (String ) iter.next(); 731 String value = (String ) optionsMap.get(option); 732 733 if (option.equals("zip")) 734 { 735 try 736 { 737 zipBackupFiles = !"false".equals(value); 738 } 739 catch (RuntimeException e) 740 { 741 zipBackupFiles = true; 742 logger 743 .warn("Invalid zip value for OctopusBackuper, available option is 'zip=[true,false]' (" 744 + value + ")"); 745 } 746 } 747 else if (option.equals("redirectOutput")) 748 { 749 try 750 { 751 redirectOutput = "true".equals(value); 752 } 753 catch (RuntimeException e) 754 { 755 redirectOutput = false; 756 logger 757 .warn("Invalid redirectOutput value for OctopusBackuper, available option is 'redirectOutput=[true,false]' (" 758 + value + ")"); 759 } 760 } 761 else 762 { 763 logger.warn("Unsupported option '" + option + "' for OctopusBackuper"); 764 } 765 } 766 logger.info("OctopusBackuper backup compression is set to " 767 + zipBackupFiles); 768 } 769 770 774 public void fetchDump(DumpTransferInfo dumpTransferInfo, String path, 775 String dumpName) throws BackupException, IOException 776 { 777 super.fetchDump(dumpTransferInfo, path, dumpName + Zipper.ZIP_EXT); 778 } 779 780 } | Popular Tags |