org.jboss.tools.runtime.ui.internal.wizard.DownloadRuntimeOperationUtility.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.runtime.ui.internal.wizard.DownloadRuntimeOperationUtility.java

Source

/*******************************************************************************
 * Copyright (c) 2014 Red Hat 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     JBoss by Red Hat
 *******************************************************************************/
package org.jboss.tools.runtime.ui.internal.wizard;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.jboss.tools.foundation.core.ecf.URLTransportUtility;
import org.jboss.tools.foundation.core.tasks.TaskModel;
import org.jboss.tools.runtime.core.extract.ExtractUtility;
import org.jboss.tools.runtime.core.extract.IOverwrite;
import org.jboss.tools.runtime.core.model.RuntimeDefinition;
import org.jboss.tools.runtime.core.model.RuntimePath;
import org.jboss.tools.runtime.core.util.RuntimeInitializerUtil;
import org.jboss.tools.runtime.ui.RuntimeUIActivator;
import org.jboss.tools.runtime.ui.internal.Messages;
import org.jboss.tools.runtime.ui.internal.dialogs.SearchRuntimePathDialog;

/**
 * Mixed class of core+ui to initiate the download, unzipping, 
 * and runtime creation for a downloaded runtime. 
 */
public class DownloadRuntimeOperationUtility {
    private static final String SEPARATOR = "/"; //$NON-NLS-1$

    protected File getNextUnusedFilename(File destination, String name) {
        String nameWithoutSuffix = null;
        if (name.indexOf('.') == -1) {
            nameWithoutSuffix = name;
        } else if (name.endsWith(".tar.gz"))
            nameWithoutSuffix = name.substring(0, name.length() - ".tar.gz".length());
        else
            nameWithoutSuffix = name.substring(0, name.lastIndexOf('.'));
        String suffix = name.substring(nameWithoutSuffix.length());
        int i = 1;
        String tmpName = null;
        File file = new File(destination, name);
        while (file.exists()) {
            tmpName = nameWithoutSuffix + "(" + i++ + ")" + suffix; //$NON-NLS-1$ //$NON-NLS-2$
            file = new File(destination, tmpName);
        }
        return file;
    }

    /**
     * 
     * @param downloadDestinationPath   The path to put the downloaded zip
     * @param urlString               The remote url
     * @param deleteOnExit            Whether to delete on exit or not
     * @return
     */
    private File getDestinationFile(String downloadDestinationPath, String urlString, boolean deleteOnExit)
            throws CoreException {
        File ret = null;
        try {
            URL url = new URL(urlString);
            String name = url.getPath();
            int slashIdx = name.lastIndexOf('/');
            if (slashIdx >= 0)
                name = name.substring(slashIdx + 1);

            File destination = new File(downloadDestinationPath);
            destination.mkdirs();
            ret = new File(destination, name);
            if (deleteOnExit) {
                ret = getNextUnusedFilename(destination, name);
            }
            if (deleteOnExit)
                ret.deleteOnExit();
            return ret;
        } catch (IOException e) {
            cancel(ret);
            IStatus s = new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID, e.getMessage(), e);
            throw new CoreException(s);
        }
    }

    private boolean cacheOutdated(File local, boolean deleteOnExit, long urlLastModified) {
        boolean download = true;
        long urlModified = 0;
        if (!deleteOnExit) {
            long cacheModified = local.lastModified();
            download = cacheModified <= 0 || cacheModified != urlModified;
        }
        return download;
    }

    private long getRemoteURLModified(String urlString, String user, String pass, IProgressMonitor monitor)
            throws CoreException, IOException {
        monitor.beginTask("Checking remote timestamp", 100);
        long l = new URLTransportUtility().getLastModified(new URL(urlString), user, pass, monitor);
        monitor.worked(100);
        monitor.done();
        return l;
    }

    private void validateInputs(String downloadDirectoryPath, String unzipDirectoryPath) throws CoreException {
        File downloadDirectory = new File(downloadDirectoryPath);
        downloadDirectory.mkdirs();
        if (!downloadDirectory.isDirectory()) {
            throw new CoreException(new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID,
                    "The '" + downloadDirectory + "' is not a directory.")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        File unzipDirectory = new File(unzipDirectoryPath);
        unzipDirectory.mkdirs();
        if (!unzipDirectory.isDirectory()) {
            throw new CoreException(new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID,
                    "The '" + unzipDirectory + "' is not a directory.")); //$NON-NLS-1$ //$NON-NLS-2$
        }
    }

    /**
     * This is a convenience method for providing no credentials.
     * 
     * @param selectedDirectory
     * @param destinationDirectory
     * @param urlString
     * @param deleteOnExit
     * @param monitor
     * @return
     * @deprecated
     */
    public IStatus downloadAndInstall(String selectedDirectory, String destinationDirectory, String urlString,
            boolean deleteOnExit, IProgressMonitor monitor) {
        return downloadAndInstall(selectedDirectory, destinationDirectory, urlString, deleteOnExit, null, null,
                null, monitor);
    }

    public IStatus downloadAndInstall(String unzipDirectoryPath, String downloadDirectoryPath, String urlString,
            boolean deleteOnExit, String user, String pass, TaskModel tm, IProgressMonitor monitor) {
        monitor.beginTask("Configuring runtime from url " + urlString, 500);
        try {
            validateInputs(downloadDirectoryPath, unzipDirectoryPath);
            File downloadedFile = downloadRemoteRuntime(unzipDirectoryPath, downloadDirectoryPath, urlString,
                    deleteOnExit, user, pass, new SubProgressMonitor(monitor, 450));

            ExtractUtility extractUtil = new ExtractUtility(downloadedFile);
            unzip(extractUtil, downloadedFile, unzipDirectoryPath, new SubProgressMonitor(monitor, 30));
            String updatedRuntimeRoot = getUpdatedUnzipPath(extractUtil, unzipDirectoryPath,
                    new SubProgressMonitor(monitor, 10));
            tm.putObject(DownloadRuntimesWizard.UNZIPPED_SERVER_HOME_DIRECTORY, updatedRuntimeRoot);
            createRuntimes(updatedRuntimeRoot, new SubProgressMonitor(monitor, 10));
        } catch (CoreException ce) {
            return ce.getStatus();
        } finally {
            monitor.done();
        }
        return Status.OK_STATUS;
    }

    public IStatus downloadAndUnzip(String unzipDirectoryPath, String downloadDirectoryPath, String urlString,
            boolean deleteOnExit, String user, String pass, TaskModel tm, IProgressMonitor monitor) {
        monitor.beginTask("Configuring runtime from url " + urlString, 500);
        try {
            validateInputs(downloadDirectoryPath, unzipDirectoryPath);
            File downloadedFile = downloadRemoteRuntime(unzipDirectoryPath, downloadDirectoryPath, urlString,
                    deleteOnExit, user, pass, new SubProgressMonitor(monitor, 450));
            ExtractUtility extractUtil = new ExtractUtility(downloadedFile);
            unzip(extractUtil, downloadedFile, unzipDirectoryPath, new SubProgressMonitor(monitor, 30));
            String updatedRuntimeRoot = getUpdatedUnzipPath(extractUtil, unzipDirectoryPath,
                    new SubProgressMonitor(monitor, 10));
            tm.putObject(DownloadRuntimesWizard.UNZIPPED_SERVER_HOME_DIRECTORY, updatedRuntimeRoot);
        } catch (CoreException ce) {
            return ce.getStatus();
        } finally {
            monitor.done();
        }
        return Status.OK_STATUS;
    }

    private File downloadRemoteRuntime(String unzipDirectoryPath, String destinationDirectory, String urlString,
            boolean deleteOnExit, String user, String pass, IProgressMonitor monitor) throws CoreException {
        monitor.beginTask("Downloading " + urlString, 1000);
        File file = null;
        try {
            file = getDestinationFile(destinationDirectory, urlString, deleteOnExit);

            long urlModified = deleteOnExit ? 0
                    : getRemoteURLModified(urlString, user, pass, new SubProgressMonitor(monitor, 100));
            boolean download = cacheOutdated(file, deleteOnExit, urlModified);

            IStatus result = null;
            if (download) {
                result = downloadFileFromRemoteUrl(file, new URL(urlString), urlModified, user, pass,
                        new SubProgressMonitor(monitor, 900));
            }
            if (!result.isOK())
                throw new CoreException(result);
            if (monitor.isCanceled())
                throw new CoreException(cancel(file));

            return file;
        } catch (IOException e) {
            cancel(file);
            throw new CoreException(new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID, e.getMessage(), e));
        } finally {
            monitor.done();
        }
    }

    private void unzip(File downloadedFile, String unzipDirectoryPath, IProgressMonitor monitor)
            throws CoreException {
        unzip(new ExtractUtility(downloadedFile), downloadedFile, unzipDirectoryPath, monitor);
    }

    private void unzip(ExtractUtility util, File downloadedFile, String unzipDirectoryPath,
            IProgressMonitor monitor) throws CoreException {
        monitor.beginTask("Unzipping " + downloadedFile.getAbsolutePath(), 1000);
        if (monitor.isCanceled())
            throw new CoreException(cancel(downloadedFile));

        IOverwrite overwriteQuery = createOverwriteFileQuery();
        final IStatus status = util.extract(new File(unzipDirectoryPath), overwriteQuery,
                new SubProgressMonitor(monitor, 1000));

        if (monitor.isCanceled())
            throw new CoreException(cancel(downloadedFile));
        if (!status.isOK())
            throw new CoreException(status);
    }

    private IStatus cancel(File f) {
        if (f != null) {
            f.deleteOnExit();
            f.delete();
        }
        return Status.CANCEL_STATUS;
    }

    private static IStatus createRuntimes(String directory, IProgressMonitor monitor) {
        monitor.subTask("Creating runtime from location " + directory); //$NON-NLS-1$
        final RuntimePath runtimePath = new RuntimePath(directory);
        List<RuntimeDefinition> runtimeDefinitions = RuntimeInitializerUtil.createRuntimeDefinitions(runtimePath,
                monitor);
        RuntimeUIActivator.getDefault().getModel().addRuntimePath(runtimePath);
        if (runtimeDefinitions.size() == 0) {
            return new Status(IStatus.ERROR, RuntimeUIActivator.PLUGIN_ID,
                    Messages.DownloadRuntimesSecondPage_No_runtime_server_found);
        } else if (runtimeDefinitions.size() > 1) {
            Display.getDefault().asyncExec(new Runnable() {
                public void run() {
                    SearchRuntimePathDialog.launchSearchRuntimePathDialog(Display.getDefault().getActiveShell(),
                            RuntimeUIActivator.getDefault().getModel().getRuntimePaths(), false, 7);
                }
            });
        } else /* size == 1 */ {
            RuntimeInitializerUtil.initializeRuntimes(runtimeDefinitions);
        }
        monitor.done();
        return Status.OK_STATUS;
    }

    private String getUpdatedUnzipPath(ExtractUtility util, String unzipDirectoryPath, IProgressMonitor monitor)
            throws CoreException {
        try {
            String root = util.getExtractedRootFolder(new SubProgressMonitor(monitor, 10));
            if (root != null) {
                File rootFile = new File(unzipDirectoryPath, root);
                if (rootFile != null && rootFile.exists()) {
                    unzipDirectoryPath = rootFile.getAbsolutePath();
                }
            }
            return unzipDirectoryPath;
        } catch (CoreException ce) {
            cancel(util.getOriginalFile());
            throw ce;
        } finally {
            monitor.done();
        }
    }

    private static IOverwrite createOverwriteFileQuery() {
        IOverwrite overwriteQuery = new IOverwrite() {
            public int overwrite(File file) {
                final String msg = NLS.bind(Messages.DownloadRuntimesSecondPage_The_file_already_exists,
                        file.getAbsolutePath());
                final String[] options = { IDialogConstants.YES_LABEL, IDialogConstants.YES_TO_ALL_LABEL,
                        IDialogConstants.NO_LABEL, IDialogConstants.NO_TO_ALL_LABEL,
                        IDialogConstants.CANCEL_LABEL };
                final int[] retVal = new int[1];
                Display.getDefault().syncExec(new Runnable() {
                    public void run() {
                        Shell shell = PlatformUI.getWorkbench().getModalDialogShellProvider().getShell();
                        MessageDialog dialog = new MessageDialog(shell,
                                Messages.DownloadRuntimesSecondPage_Question, null, msg, MessageDialog.QUESTION,
                                options, 0) {
                            protected int getShellStyle() {
                                return super.getShellStyle() | SWT.SHEET;
                            }
                        };
                        dialog.open();
                        retVal[0] = dialog.getReturnCode();
                    }
                });
                return retVal[0];
            }
        };
        return overwriteQuery;
    }

    private IStatus downloadFileFromRemoteUrl(File toFile, URL url, long remoteUrlModified, String user,
            String pass, IProgressMonitor monitor) throws IOException {
        OutputStream out = null;
        try {
            out = new BufferedOutputStream(new FileOutputStream(toFile));
            IStatus result = new URLTransportUtility().download(toFile.getName(), url.toExternalForm(), user, pass,
                    out, -1, monitor);
            out.flush();
            out.close();
            if (remoteUrlModified > 0) {
                toFile.setLastModified(remoteUrlModified);
            }
            return result;
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

}