com.cloudbees.eclipse.run.ui.wizards.CBWebAppWizardFinishOperation.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudbees.eclipse.run.ui.wizards.CBWebAppWizardFinishOperation.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Cloud Bees, Inc.
 * All rights reserved. 
 * This program is 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:
 *    Cloud Bees, Inc. - initial API and implementation 
 *******************************************************************************/
package com.cloudbees.eclipse.run.ui.wizards;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.internal.ui.wizards.buildpaths.BuildPathsBlock;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;

import com.cloudbees.eclipse.core.ClickStartService;
import com.cloudbees.eclipse.core.CloudBeesCorePlugin;
import com.cloudbees.eclipse.core.CloudBeesException;
import com.cloudbees.eclipse.core.CloudBeesNature;
import com.cloudbees.eclipse.core.NatureUtil;
import com.cloudbees.eclipse.core.gc.api.ClickStartCreateResponse;
import com.cloudbees.eclipse.core.gc.api.ClickStartTemplate;
import com.cloudbees.eclipse.dev.scm.egit.ForgeEGitSync;
import com.cloudbees.eclipse.run.core.CBRunCoreActivator;
import com.cloudbees.eclipse.run.core.NewClickStartProjectHook;
import com.cloudbees.eclipse.run.ui.CBRunUiActivator;
import com.cloudbees.eclipse.run.ui.popup.actions.ReloadRunAtCloudAction;
import com.cloudbees.eclipse.ui.CloudBeesUIPlugin;
import com.cloudbees.eclipse.ui.wizard.Failure;

public class CBWebAppWizardFinishOperation implements IRunnableWithProgress {

    private static final String ERROR_TITLE = "Error";
    private static final String ERROR_MSG = "Received error while creating new project";

    private final static boolean SUPPORT_CANCEL = false;;

    private final CBWebAppWizard wizard;
    private final CBProjectNameAndLocationPage nameAndLocPage;
    private final ClickStartTemplateWizardPage clickStartPage;

    private IProject project;
    private boolean useDefaultLocation;
    private URI uri;
    private ImportOperation importOperation;
    //private boolean isMakeJenkinsJob;
    private boolean isAddNewRepo;
    private ClickStartTemplate template;
    private String jobName;
    private URI locationURI;
    private Failure<Exception> failure;

    public CBWebAppWizardFinishOperation(final CBWebAppWizard wizard) {
        this.wizard = wizard;
        this.nameAndLocPage = wizard.getNameAndLocationPage();
        this.clickStartPage = wizard.getClickStartPage();
        prepare();
    }

    private void prepare() {
        String projectName = this.nameAndLocPage.getProjectName();

        IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
        this.uri = this.nameAndLocPage.getProjectLocationURI();
        this.useDefaultLocation = this.uri == null;
        if (this.useDefaultLocation) {
            this.uri = workspaceRoot.getLocationURI();
        }

        this.project = workspaceRoot.getProject(projectName);
        IPath path = new Path(this.uri.getPath()).append(projectName);
        IPath containerPath = this.project.getFullPath();
        File source = path.toFile();
        IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE;
        IOverwriteQuery overwriteQuery = new IOverwriteQuery() {
            @Override
            public String queryOverwrite(final String pathString) {
                return IOverwriteQuery.NO_ALL;
            }
        };

        this.importOperation = new ImportOperation(containerPath, source, structureProvider, overwriteQuery);
        //this.isMakeJenkinsJob = this.clickStartPage.isMakeNewJob();
        //this.isAddNewRepo = this.clickStartPage.isAddNewRepository();
        this.template = this.clickStartPage.getTemplate();
        //this.jobName = this.clickStartPage.getJobNameText();
        this.locationURI = URIUtil.append(this.uri, projectName);
        this.failure = new Failure<Exception>();

        CloudBeesUIPlugin plugin = CloudBeesUIPlugin.getDefault();
        /*JenkinsInstance instance = CBWebAppWizardFinishOperation.this.clickStartPage.getJenkinsInstance();
        if (instance != null) {
          this.jenkinsService = plugin.lookupJenkinsService(instance);
        }*/
    }

    private static void handleException(final String msg, final IStatus status) {
        if (status.getException() != null) {
            CBRunUiActivator.logError(status.getException());
        }
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                ErrorDialog.openError(CBRunUiActivator.getDefault().getWorkbench().getDisplay().getActiveShell(),
                        ERROR_TITLE, msg, status);
            }
        });

    }

    @Override
    public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {

        org.eclipse.core.runtime.jobs.Job job = new org.eclipse.core.runtime.jobs.Job(
                "Provisioning CloudBees ClickStart project. This may take a few minutes.") {

            @Override
            protected void canceling() {
                // notify user "ClickStart project provisioning cannot be cancelled."
                //MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Cannot be cancelled.", "ClickStart project provisioning cannot be cancelled.");

                MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Cannot be canceled.",
                        "This operation cannot be canceled.");

                //MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Cancelled.", "Partially cancelled:\n1) Provisioning cannot be cancelled and will continue.\n2) After the provisioning completes Eclipse won't be configured for the app.");

                //super.canceling();
            }

            @Override
            protected IStatus run(final IProgressMonitor monitor) {

                monitor.beginTask("Provisioning CloudBees ClickStart project. This may take a few minutes.", 100);
                try {

                    ClickStartService service = CloudBeesCorePlugin.getDefault().getClickStartService();
                    String accountName = CloudBeesCorePlugin.getDefault().getGrandCentralService()
                            .getActiveAccountName();
                    monitor.worked(25);

                    monitor.setTaskName("Creating '" + nameAndLocPage.getProjectName() + "' for account '"
                            + accountName + "' using ClickStart template '"
                            + CBWebAppWizardFinishOperation.this.template.name + "'");

                    // Invoke provisioning request in a separate job
                    // If request returns keep polling and reporting progress of the provisioning to the job label
                    // As progress=100, bring up a modal background job while configuring and refreshing workspace.
                    // Setup:
                    // Clone from the repo and have git repo accessible
                    // Configure datatools connection to the database
                    // Refresh jenkins job lists and run@cloud app list.

                    ClickStartCreateResponse resp = service.create(CBWebAppWizardFinishOperation.this.template.id,
                            accountName, nameAndLocPage.getProjectName());

                    // Set appId for the project settings

                    String resId = resp.reservationId;
                    int pr = service.getCreateProgress(resId);
                    int lastpr = pr;

                    if (SUPPORT_CANCEL && monitor.isCanceled()) {
                        return Status.CANCEL_STATUS;
                    }

                    monitor.beginTask(
                            "Waiting for the servers to provision ClickStart components. This may take a few minutes.",
                            100);
                    monitor.worked(pr);
                    while (pr < 100) {
                        Thread.currentThread().sleep(1000);
                        lastpr = pr;
                        if (SUPPORT_CANCEL && monitor.isCanceled()) {
                            return Status.CANCEL_STATUS;
                        }
                        pr = service.getCreateProgress(resId);
                        if (SUPPORT_CANCEL && monitor.isCanceled()) {
                            return Status.CANCEL_STATUS;
                        }
                        monitor.worked(pr - lastpr);
                    }

                    if (SUPPORT_CANCEL && monitor.isCanceled()) {
                        return Status.CANCEL_STATUS;
                    }

                    monitor.beginTask("Configuring local workspace for CloudBees ClickStart project", 100);

                    //if (CBWebAppWizardFinishOperation.this.isAddNewRepo) {
                    //GrandCentralService service = CloudBeesCorePlugin.getDefault().getGrandCentralService();
                    //service.getForgeSyncService().addToRepository(this.repo, this.project, monitor);
                    //}

                    if (project == null) {
                        return Status.OK_STATUS;
                    }

                    // Clone generated project.
                    monitor.subTask("Cloning git repository into the newly created project. From: " + resp.forgeUrl
                            + " to " + project.getLocation());
                    ForgeEGitSync.cloneRepo(resp.source, CBWebAppWizardFinishOperation.this.locationURI, monitor);
                    monitor.worked(30);

                    monitor.subTask(
                            "Creating local project '" + CBWebAppWizardFinishOperation.this.template.id + "'");
                    if (CBWebAppWizardFinishOperation.this.useDefaultLocation) {
                        CBWebAppWizardFinishOperation.this.importOperation
                                .setContext(CBWebAppWizardFinishOperation.this.wizard.getShell());
                        CBWebAppWizardFinishOperation.this.importOperation.setCreateContainerStructure(false);
                        CBWebAppWizardFinishOperation.this.importOperation.run(monitor);
                    } else {
                        BuildPathsBlock.createProject(project, CBWebAppWizardFinishOperation.this.locationURI,
                                monitor);
                    }

                    monitor.worked(10);
                    monitor.subTask("Adding CloudBees and Java project nature");
                    //JavaCore.NATURE_ID
                    NatureUtil.addNatures(project, new String[] { CloudBeesNature.NATURE_ID, JavaCore.NATURE_ID },
                            monitor);
                    monitor.worked(10);

                    String[] s1 = resp.appUrl.split("\\.");
                    String account = s1[1];
                    int idx1 = s1[0].lastIndexOf('/');
                    String appId = s1[0].substring(idx1 + 1);

                    project.setPersistentProperty(CloudBeesCorePlugin.PRJ_APPID_KEY, appId);
                    project.setPersistentProperty(CloudBeesCorePlugin.PRJ_ACCOUNT_KEY, account);

                    // Refresh project to refresh the project nature
                    project.refreshLocal(IProject.DEPTH_INFINITE, monitor);

                    // Let's add back the CB nature in case it was not configured by the maven script
                    NatureUtil.addNatures(project, new String[] { CloudBeesNature.NATURE_ID, JavaCore.NATURE_ID },
                            monitor);

                    // Run ant or maven build task to generate eclipse files for the project

                    // Refresh run@cloud and dev@cloud items
                    CloudBeesUIPlugin.getDefault().reloadAllCloudJenkins(true);
                    ReloadRunAtCloudAction.reload();

                    for (NewClickStartProjectHook hook : getHooks()) {
                        hook.hookProject(resp, project, monitor);
                    }

                    // initialize database components
                    /*          Provisioning database for: null
                    COMPONENT: key:Source_repository; name:Source repository; url:ssh://git@git.cloudbees.com/grandomstate/sw1.git
                    COMPONENT: key:Jenkins_build; name:Jenkins build; url:null
                    COMPONENT: key:Web_Application_sw1; name:Web Application sw1; url:http://sw1.grandomstate.cloudbees.net
                    COMPONENT: key:Database_sw1_fu9l; name:Database sw1_fu9l; url:null
                    */

                    /*project.accept(new IResourceVisitor() {
                      @Override
                      public boolean visit(final IResource resource) throws CoreException {
                        if (resource.getType() == IResource.FILE && "war".equalsIgnoreCase(resource.getFileExtension())) {
                          //wars.add(resource.getProjectRelativePath().toOSString());
                        }
                        return true;
                      }
                    });
                    */
                    return Status.OK_STATUS;
                } catch (Exception e) {
                    if (e instanceof CloudBeesException) {
                        e = (Exception) e.getCause();
                    }

                    Throwable iterT = e;
                    Throwable realT = e;
                    while (iterT.getCause() != null) {
                        iterT = iterT.getCause();
                        if (iterT.getMessage() != null && iterT.getMessage().contains("CloudBees Forge")) {
                            realT = iterT;
                        }
                    }

                    String msg = realT.getLocalizedMessage();
                    if (msg == null) {
                        msg = realT.getMessage();
                    }

                    CBRunUiActivator.getDefault().getLogger().error(msg, realT);

                    String rmsg = "Failed to complete ClickStart project provisioning: " + msg;

                    if (realT instanceof CloudBeesException && realT.getMessage() != null) {
                        rmsg = realT.getMessage();
                    }

                    return new Status(IStatus.ERROR, CBRunUiActivator.PLUGIN_ID, rmsg, realT);

                } finally {
                    monitor.done();
                }
            }

        };

        job.setUser(true);
        job.schedule();

    }

    public boolean performFinish() {

        try {
            //CBRunCoreScripts.executeCopySampleWebAppScript(this.uri.getPath(), this.project.getName());
            this.wizard.getContainer().run(true, false, this);

            /*if (CBWebAppWizardFinishOperation.this.isMakeJenkinsJob) {
              CBWizardSupport
                  .makeJenkinsJob(createConfigXML(), this.jenkinsService, this.jobName, this.wizard.getContainer());
            }
            */
            if (this.failure.cause != null) {
                handleException(this.failure.cause);
            }
        } catch (Exception e) {
            handleException(e);
        }

        IWorkingSet[] workingSets = this.nameAndLocPage.getWorkingSets();
        PlatformUI.getWorkbench().getWorkingSetManager().addToWorkingSets(this.project, workingSets);

        return true;
    }

    private void handleException(final Exception ex) {
        ex.printStackTrace();
        IStatus status = new Status(IStatus.ERROR, CBRunUiActivator.PLUGIN_ID, ex.getMessage(), ex);
        ErrorDialog.openError(this.wizard.getShell(), ERROR_TITLE, ERROR_MSG, status);
    }

    /*  private String createConfigXML() throws Exception {
        if (this.isAddNewRepo) {
    String description = "Builds " + this.project.getName() + " with SCM support";
        
    String url = this.repo.url;
    if (!url.endsWith("/")) {
      url += "/";
    }
    url += this.project.getName();
        
    return Utils.createSCMConfig(description, url);
        
        } else {
    String description = "Builds " + this.project.getName() + " without SCM support";
    return Utils.createEmptyConfig(description);
        }
      }
    */

    private List<NewClickStartProjectHook> getHooks() throws CoreException {
        List<NewClickStartProjectHook> hooks = new ArrayList<NewClickStartProjectHook>();

        IExtension[] extensions = Platform.getExtensionRegistry()
                .getExtensionPoint(CBRunCoreActivator.PLUGIN_ID, "newClickStartProjectHook").getExtensions();

        for (IExtension extension : extensions) {
            for (IConfigurationElement element : extension.getConfigurationElements()) {
                Object executableExtension = element.createExecutableExtension("defaultHandler");
                if (executableExtension instanceof NewClickStartProjectHook) {
                    hooks.add((NewClickStartProjectHook) executableExtension);
                }
            }
        }

        return hooks;
    }

}