| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more contributor license |
| * agreements. See the NOTICE file distributed with this work for additional information regarding |
| * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the License. You may obtain a |
| * copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package org.apache.geode.internal.cache.backup; |
| |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.apache.geode.internal.lang.SystemUtils; |
| |
| /** |
| * This class is used to automatically generate a restore script for a backup. It keeps a list of |
| * files that were backed up, and a list of files that we should test for to avoid overriding when |
| * we restore the backup. |
| * |
| * <p> |
| * It generates either a restore.sh for unix or a restore.bat for windows. |
| */ |
| class RestoreScript { |
| |
| static final String INCREMENTAL_MARKER_COMMENT = |
| "Incremental backup. Restore baseline originals from previous backups."; |
| |
| static final String REFUSE_TO_OVERWRITE_MESSAGE = "Backup not restored. Refusing to overwrite "; |
| |
| private static final String[] ABOUT_SCRIPT_COMMENT = |
| {"Restore a backup of gemfire persistent data to the location it was backed up", |
| "from. This script will refuse to restore if the original data still exists.", |
| "This script was automatically generated by the gemfire backup utility.",}; |
| |
| private static final String EXISTENCE_CHECK_COMMENT = |
| "Test for existing originals. If they exist, do not restore the backup."; |
| |
| private static final String RESTORE_DATA_COMMENT = "Restore data"; |
| |
| private final ScriptGenerator generator; |
| private final Map<File, File> baselineFiles = new HashMap<>(); |
| private final Map<File, File> backedUpFiles = new LinkedHashMap<>(); |
| private final List<File> existenceTests = new ArrayList<>(); |
| |
| RestoreScript() { |
| this(SystemUtils.isWindows() ? new WindowsScriptGenerator() : new UnixScriptGenerator()); |
| } |
| |
| private RestoreScript(final ScriptGenerator generator) { |
| this.generator = generator; |
| } |
| |
| void addBaselineFiles(final Map<File, File> baselineFiles) { |
| this.baselineFiles.putAll(baselineFiles); |
| } |
| |
| void addBaselineFile(File baseline, File absoluteFile) { |
| baselineFiles.put(baseline, absoluteFile); |
| } |
| |
| public void addFile(final File originalFile, final File backupFile) { |
| backedUpFiles.put(backupFile, originalFile.getAbsoluteFile()); |
| } |
| |
| void addExistenceTest(final File originalFile) { |
| existenceTests.add(originalFile.getAbsoluteFile()); |
| } |
| |
| File generate(final File outputDir) throws IOException { |
| File outputFile = new File(outputDir, generator.getScriptName()); |
| try (BufferedWriter writer = Files.newBufferedWriter(outputFile.toPath())) { |
| |
| writePreamble(writer); |
| writeAbout(writer); |
| writeExistenceTest(writer); |
| writeRestoreData(writer, outputDir.toPath()); |
| writeIncrementalData(writer); |
| generator.writeExit(writer); |
| } |
| |
| outputFile.setExecutable(true, true); |
| return outputFile; |
| } |
| |
| private void writePreamble(BufferedWriter writer) throws IOException { |
| generator.writePreamble(writer); |
| writer.newLine(); |
| } |
| |
| private void writeAbout(BufferedWriter writer) throws IOException { |
| for (String comment : ABOUT_SCRIPT_COMMENT) { |
| generator.writeComment(writer, comment); |
| } |
| writer.newLine(); |
| } |
| |
| private void writeExistenceTest(BufferedWriter writer) throws IOException { |
| generator.writeComment(writer, EXISTENCE_CHECK_COMMENT); |
| for (File file : existenceTests) { |
| generator.writeExistenceTest(writer, file); |
| } |
| writer.newLine(); |
| } |
| |
| private void writeRestoreData(BufferedWriter writer, Path outputDir) throws IOException { |
| generator.writeComment(writer, RESTORE_DATA_COMMENT); |
| for (Map.Entry<File, File> entry : backedUpFiles.entrySet()) { |
| File backup = entry.getKey(); |
| String[] backupFiles = backup.list(); |
| boolean backupHasFiles = |
| backup.isDirectory() && backupFiles != null && backupFiles.length != 0; |
| backup = outputDir.relativize(backup.toPath()).toFile(); |
| File original = entry.getValue(); |
| if (original.isDirectory()) { |
| generator.writeCopyDirectoryContents(writer, backup, original, backupHasFiles); |
| } else { |
| generator.writeCopyFile(writer, backup, original); |
| } |
| } |
| } |
| |
| private void writeIncrementalData(BufferedWriter writer) throws IOException { |
| // Write out baseline file copies in restore script (if there are any) if this is a restore |
| // for an incremental backup |
| if (baselineFiles.isEmpty()) { |
| return; |
| } |
| |
| writer.newLine(); |
| generator.writeComment(writer, INCREMENTAL_MARKER_COMMENT); |
| for (Map.Entry<File, File> entry : baselineFiles.entrySet()) { |
| generator.writeCopyFile(writer, entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| void addUserFile(File original, File dest) { |
| addExistenceTest(original); |
| addFile(original, dest); |
| } |
| } |