package org.springframework.roo.file.undo; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.logging.Logger; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.springframework.roo.support.logging.HandlerUtils; import org.springframework.roo.support.util.FileUtils; /** * {@link UndoableOperation} to delete a directory. * * @author Ben Alex * @since 1.0 */ public class DeleteDirectory implements UndoableOperation { private static final Logger LOGGER = HandlerUtils.getLogger(DeleteDirectory.class); private static final File TEMP_DIRECTORY = new File(System.getProperty("java.io.tmpdir")); private final File actual; private final File backup; private final FilenameResolver filenameResolver; /** * Constructor that doesn't allow a reason to be given * * @param undoManager (required) * @param filenameResolver (required) * @param directory the directory to delete; must be an existing directory * (not a file) * @deprecated use the constructor that allows a reason to be provided */ @Deprecated public DeleteDirectory(final UndoManager undoManager, final FilenameResolver filenameResolver, final File directory) { this(undoManager, filenameResolver, directory, null); } /** * Constructor that allows a reason to be given * * @param undoManager (required) * @param filenameResolver (required) * @param directory the directory to delete; must be an existing directory * (not a file) * @param reason the reason for the directory's deletion; can be blank * @since 1.2.0 */ public DeleteDirectory(final UndoManager undoManager, final FilenameResolver filenameResolver, final File directory, final String reason) { Validate.notNull(undoManager, "Undo manager required"); Validate.notNull(directory, "Actual file required"); Validate.notNull(filenameResolver, "Filename resolver required"); Validate.isTrue(directory.exists(), "File '%s' must exist", directory); Validate.isTrue(directory.isDirectory(), "Path '%s' must be a directory (not a file)", directory); Validate.isTrue(TEMP_DIRECTORY.isDirectory(), "Temporary directory '%s' is not a directory", TEMP_DIRECTORY); actual = directory; backup = new File(TEMP_DIRECTORY, "tmp_" + new Date().getTime() + "_dir"); this.filenameResolver = filenameResolver; if (!FileUtils.copyRecursively(directory, backup, true)) { throw new IllegalStateException("Unable to create a complete backup of directory '" + directory + "'"); } try { org.apache.commons.io.FileUtils.deleteDirectory(directory); } catch (IOException e) { throw new IllegalStateException("Unable to completely delete directory '" + directory + "'"); } undoManager.add(this); String deletionMessage = "Deleted " + filenameResolver.getMeaningfulName(directory); if (StringUtils.isNotBlank(reason)) { deletionMessage += " - " + reason.trim(); } LOGGER.fine(deletionMessage); } public void reset() { // Fix for ROO-1555 boolean success = true; try { org.apache.commons.io.FileUtils.deleteDirectory(backup); } catch (IOException e) { success = false; } try { if (success) { LOGGER.finest("Reset manage " + filenameResolver.getMeaningfulName(backup)); } else { backup.deleteOnExit(); LOGGER.fine("Reset failed " + filenameResolver.getMeaningfulName(backup)); } } catch (final Throwable ignore) { backup.deleteOnExit(); LOGGER.fine("Reset failed " + filenameResolver.getMeaningfulName(backup)); } } public boolean undo() { final boolean success = FileUtils.copyRecursively(backup, actual, false); LOGGER.fine((success ? "Undo delete " : "Undo failed ") + filenameResolver.getMeaningfulName(actual)); return success; } }