All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.izforge.izpack.uninstaller.Destroyer Maven / Gradle / Ivy

There is a newer version: 5.2.3
Show newest version
/*
 * IzPack - Copyright 2001-2012 Julien Ponge, All Rights Reserved.
 *
 * http://izpack.org/
 * http://izpack.codehaus.org/
 *
 * Licensed 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 com.izforge.izpack.uninstaller;

import static com.izforge.izpack.api.handler.Prompt.Type.ERROR;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.izforge.izpack.api.event.ProgressListener;
import com.izforge.izpack.api.handler.Prompt;
import com.izforge.izpack.uninstaller.event.UninstallerListeners;
import com.izforge.izpack.uninstaller.resource.Executables;
import com.izforge.izpack.uninstaller.resource.InstallLog;
import com.izforge.izpack.uninstaller.resource.RootScripts;


/**
 * The files destroyer class.
 *
 * @author Julien Ponge
 * @author Tim Anderson
 */
public class Destroyer implements Runnable
{

    /**
     * The log of installed files.
     */
    private final InstallLog log;

    /**
     * The uninstaller listeners.
     */
    private final UninstallerListeners listeners;

    /**
     * The executables.
     */
    private final Executables executables;

    /**
     * The root scripts.
     */
    private final RootScripts rootScripts;

    /**
     * The prompt.
     */
    private Prompt prompt;

    /**
     * The progress listener. May be {@code null}.
     */
    private ProgressListener listener;

    /**
     * True if the destroyer must force recursive deletion.
     */
    private boolean forceDelete;

    /**
     * Tracks the no. of files that couldn't be deleted.
     */
    private List failed = new ArrayList();

    /**
     * The logger.
     */
    private static final Logger logger = Logger.getLogger(Destroyer.class.getName());

    /**
     * The constructor.
     *
     * @param log       the installation log
     * @param listeners the uninstaller listeners
     * @param prompt    the prompt
     */
    public Destroyer(InstallLog log, UninstallerListeners listeners,
                     Executables executables, RootScripts rootScripts, Prompt prompt)
    {
        this.log = log;
        this.listeners = listeners;
        this.executables = executables;
        this.rootScripts = rootScripts;
        this.prompt = prompt;
    }

    /**
     * Sets the prompt.
     *
     * @param prompt the prompt
     */
    public void setPrompt(Prompt prompt)
    {
        this.prompt = prompt;
    }

    /**
     * Registers a listener to be notified of progress.
     *
     * @param listener the listener. May be {@code null}
     */
    public void setProgressListener(ProgressListener listener)
    {
        this.listener = listener;
    }

    /**
     * Determines if any remaining files should be removed after the installed files are removed.
     *
     * @param force if true, remove remaining files
     */
    public void setForceDelete(boolean force)
    {
        this.forceDelete = force;
    }

    /**
     * Runs the destroyer.
     */
    @Override
    public void run()
    {
        try
        {
            if (!executables.run())
            {
                logger.severe("An executable has failed. Destroyer will not be run");
            }
            else
            {
                destroy();
            }
        }
        catch (Throwable exception)
        {
            if (listener != null)
            {
                listener.stopAction();
            }
            logger.log(Level.SEVERE, exception.getMessage(), exception);

            StringWriter trace = new StringWriter();
            exception.printStackTrace(new PrintWriter(trace));

            prompt.message(ERROR, "exception caught", trace.toString());
        }
    }

    /**
     * Returns any files that could not be removed.
     *
     * @return the files
     */
    public List getFailedToDelete()
    {
        return failed;
    }

    /**
     * Deletes installed files, runs any root scripts, and cleans up remaining files if required.
     *
     * @throws Exception for any error
     */
    private void destroy() throws Exception
    {
        List files = log.getInstalled();
        int size = files.size();
        listeners.beforeDeletion(files, listener);
        if (listener != null)
        {
            listener.startAction("destroy", size);
        }

        for (int i = 0; i < size; i++)
        {
            File file = files.get(i);
            listeners.beforeDelete(file, listener);

            delete(file);

            listeners.afterDelete(file, listener);
            if (listener != null)
            {
                listener.progress(i, file.getAbsolutePath());
            }
        }

        listeners.afterDeletion(files, listener);

        rootScripts.run();

        // We make a complementary cleanup
        if (listener != null)
        {
            listener.progress(log.getInstalled().size(), "[ cleanups ]");
        }

        File installPath = new File(log.getInstallPath());
        cleanup(installPath);

        // verify that the files no longer exist. Check this here, as the root scripts may have performed cleanup.
        checkDeletion(files, installPath);

        if (listener != null)
        {
            listener.stopAction();
        }
    }

    /**
     * Verifies that the installed files have been deleted.
     *
     * @param files       the files to check
     * @param installPath the installation path
     */
    private void checkDeletion(List files, File installPath)
    {
        failed.clear();
        for (File f : files)
        {
            if (f.exists())
            {
                failed.add(f);
            }
        }
        if (installPath.exists())
        {
            failed.add(installPath);
        }
    }

    /**
     * Recursively deletes a directory tree.
     *
     * @param file the file to delete
     */
    private void cleanup(File file)
    {
        if (file.isDirectory())
        {
            File[] files = file.listFiles();
            if (files != null)
            {
                for (File child : files)
                {
                    cleanup(child);
                }
            }
            delete(file);
        }
        else if (forceDelete)
        {
            delete(file);
        }
    }

    /**
     * Deletes a file.
     *
     * @param file the file to delete
     */
    private void delete(File file)
    {
        if (file.exists() && !file.delete())
        {
            logger.info("Failed to delete: " + file);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy