com.microsoft.intellij.forms.WebSiteDeployForm.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.intellij.forms.WebSiteDeployForm.java

Source

/**
 * Copyright (c) Microsoft Corporation
 * <p/>
 * All rights reserved.
 * <p/>
 * MIT License
 * <p/>
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * <p/>
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of
 * the Software.
 * <p/>
 * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.microsoft.intellij.forms;

import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
import com.microsoft.intellij.AzurePlugin;
import com.microsoft.intellij.AzureSettings;
import com.microsoft.intellij.ui.components.DefaultDialogWrapper;
import com.microsoft.intellij.util.AppInsightsCustomEvent;
import com.microsoft.intellij.util.PluginUtil;
import com.microsoft.intellij.wizards.WizardCacheManager;
import com.microsoft.tooling.msservices.components.DefaultLoader;
import com.microsoft.tooling.msservices.helpers.IDEHelper.ArtifactDescriptor;
import com.microsoft.tooling.msservices.helpers.IDEHelper.ProjectDescriptor;
import com.microsoft.tooling.msservices.helpers.NotNull;
import com.microsoft.tooling.msservices.helpers.azure.AzureCmdException;
import com.microsoft.tooling.msservices.helpers.azure.AzureManager;
import com.microsoft.tooling.msservices.helpers.azure.AzureManagerImpl;
import com.microsoft.tooling.msservices.helpers.tasks.CancellableTask;
import com.microsoft.tooling.msservices.helpers.tasks.CancellableTask.CancellableTaskHandle;
import com.microsoft.tooling.msservices.model.Subscription;
import com.microsoft.tooling.msservices.model.ws.WebSite;
import com.microsoft.tooling.msservices.model.ws.WebSiteConfiguration;
import com.microsoft.tooling.msservices.model.ws.WebSitePublishSettings;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutionException;

import static com.microsoft.intellij.ui.messages.AzureBundle.message;

public class WebSiteDeployForm extends DialogWrapper {
    private JPanel mainPanel;
    private JList webSiteJList;
    private JButton buttonEditSubscriptions;
    private JButton buttonAddApp;
    private JCheckBox chkBoxDeployRoot;
    private JButton buttonDel;
    private Module module;
    private Project project;
    private WebSite selectedWebSite;
    private CancellableTaskHandle fillListTaskHandle;
    private String nameToSelect = "";
    List<Subscription> subscriptionList = new ArrayList<Subscription>();
    List<WebSite> webSiteList = new ArrayList<WebSite>();
    Map<WebSite, WebSiteConfiguration> webSiteConfigMap = new HashMap<WebSite, WebSiteConfiguration>();

    public WebSiteDeployForm(Module module) {
        super(module.getProject(), true, IdeModalityType.PROJECT);
        this.module = module;
        this.project = module.getProject();
        setTitle(message("webAppTtl"));
        buttonAddApp.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                createWebApp();
            }
        });
        buttonDel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                deleteWebApp();
            }
        });
        buttonEditSubscriptions.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                if (subscriptionList.isEmpty()) {
                    editSubscriptions(true);
                } else {
                    editSubscriptions(false);
                }
            }
        });
        init();
        String nameToSelectCached = DefaultLoader.getIdeHelper()
                .getProperty(String.format("%s.webapps", module.getName()));
        if (nameToSelectCached != null) {
            nameToSelect = nameToSelectCached;
        }
        fillList();
    }

    void deleteWebApp() {
        if (selectedWebSite != null) {
            String name = selectedWebSite.getName();
            int choice = Messages.showOkCancelDialog(String.format(message("delMsg"), name), message("delTtl"),
                    Messages.getQuestionIcon());
            if (choice == Messages.OK) {
                try {
                    AzureManagerImpl.getManager().deleteWebSite(selectedWebSite.getSubscriptionId(),
                            selectedWebSite.getWebSpaceName(), name);
                    webSiteList.remove(webSiteJList.getSelectedIndex());
                    webSiteConfigMap.remove(selectedWebSite);
                    AzureSettings.getSafeInstance(AzurePlugin.project).saveWebApps(webSiteConfigMap);
                    selectedWebSite = null;
                    if (webSiteConfigMap.isEmpty()) {
                        setMessages("There are no Azure web apps in the imported subscriptions.");
                    } else {
                        setWebApps(webSiteConfigMap);
                    }
                } catch (AzureCmdException e) {
                    String msg = message("delWebErr") + "\n"
                            + String.format(message("webappExpMsg"), e.getMessage());
                    PluginUtil.displayErrorDialogAndLog(message("errTtl"), msg, e);
                }
            }
        } else {
            PluginUtil.displayErrorDialog(message("errTtl"), "Select a web app container to delete.");
        }
    }

    @Override
    protected boolean postponeValidation() {
        return true;
    }

    @org.jetbrains.annotations.Nullable
    @Override
    protected ValidationInfo doValidate() {
        return (selectedWebSite != null
                && isDeployable(webSiteConfigMap, webSiteList, webSiteJList.getSelectedIndex())) ? null
                        : new ValidationInfo("Select a valid web app container as the target for the deployment.",
                                webSiteJList);
    }

    @org.jetbrains.annotations.Nullable
    @Override
    protected JComponent createCenterPanel() {
        return mainPanel;
    }

    @Override
    protected void dispose() {
        if (fillListTaskHandle != null && !fillListTaskHandle.isFinished()) {
            fillListTaskHandle.cancel();
        }
        super.dispose();
    }

    public String deploy() throws AzureCmdException {
        String url = "";
        ProjectDescriptor projectDescriptor = new ProjectDescriptor(project.getName(),
                project.getBasePath() == null ? "" : project.getBasePath());
        WebSite webSite = this.selectedWebSite;

        AzureManager manager = AzureManagerImpl.getManager();
        ArtifactDescriptor artifactDescriptor = manager.getWebArchiveArtifact(projectDescriptor);
        if (artifactDescriptor != null && webSite != null) {
            manager.deployWebArchiveArtifact(projectDescriptor, artifactDescriptor, webSite,
                    chkBoxDeployRoot.isSelected());
            WebSitePublishSettings webSitePublishSettings = manager.getWebSitePublishSettings(
                    webSite.getSubscriptionId(), webSite.getWebSpaceName(), webSite.getName());
            WebSitePublishSettings.PublishProfile profile = webSitePublishSettings.getPublishProfileList().get(0);
            String destAppUrl = "";
            if (profile != null) {
                destAppUrl = profile.getDestinationAppUrl();
                url = destAppUrl;
                if (!chkBoxDeployRoot.isSelected()) {
                    String artifactName = artifactDescriptor.getName().replaceAll("[^a-zA-Z0-9_-]+", "");
                    url = url + "/" + artifactName;
                }
            }
            AppInsightsCustomEvent.createFTPEvent("WebAppFTP", destAppUrl, artifactDescriptor.getName(),
                    selectedWebSite.getSubscriptionId());
        }
        DefaultLoader.getIdeHelper().setProperty(String.format("%s.webapps", module.getName()),
                selectedWebSite.getName());
        return url;
    }

    private void fillList() {
        if (fillListTaskHandle != null && !fillListTaskHandle.isFinished()) {
            fillListTaskHandle.cancel();
        }

        webSiteJList.setModel(getMessageListModel("(Loading Web Apps...)"));

        for (ListSelectionListener selectionListener : webSiteJList.getListSelectionListeners()) {
            webSiteJList.removeListSelectionListener(selectionListener);
        }

        ProjectDescriptor projectDescriptor = new ProjectDescriptor(project.getName(),
                project.getBasePath() == null ? "" : project.getBasePath());

        try {
            fillListTaskHandle = DefaultLoader.getIdeHelper().runInBackground(projectDescriptor,
                    "Retrieving web apps info...", null, new CancellableTask() {
                        final AzureManager manager = AzureManagerImpl.getManager();
                        final Object lock = new Object();

                        CancellationHandle cancellationHandle;

                        @Override
                        public synchronized void run(final CancellationHandle cancellationHandle) throws Throwable {
                            this.cancellationHandle = cancellationHandle;
                            subscriptionList = manager.getSubscriptionList();
                            webSiteConfigMap = new HashMap<WebSite, WebSiteConfiguration>();
                            if (subscriptionList.size() > 0) {
                                if (manager.authenticated()) {
                                    // authenticated using AD. Proceed for Web Apps retrieval
                                    List<ListenableFuture<Void>> subscriptionFutures = new ArrayList<ListenableFuture<Void>>();

                                    for (final Subscription subscription : subscriptionList) {
                                        if (cancellationHandle.isCancelled()) {
                                            return;
                                        }

                                        final SettableFuture<Void> subscriptionFuture = SettableFuture.create();

                                        DefaultLoader.getIdeHelper().executeOnPooledThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                loadWebSiteConfigurations(subscription, subscriptionFuture);
                                            }
                                        });

                                        subscriptionFutures.add(subscriptionFuture);
                                    }

                                    try {
                                        Futures.allAsList(subscriptionFutures).get();
                                    } catch (InterruptedException e) {
                                        throw new AzureCmdException(e.getMessage(), e);
                                    } catch (ExecutionException e) {
                                        throw new AzureCmdException(e.getCause().getMessage(), e.getCause());
                                    }
                                } else {
                                    // imported publish settings file. Clear subscription
                                    manager.clearImportedPublishSettingsFiles();
                                    WizardCacheManager.clearSubscriptions();
                                    subscriptionList = manager.getSubscriptionList();
                                }
                            }
                        }

                        @Override
                        public void onCancel() {
                        }

                        @Override
                        public void onSuccess() {
                            DefaultLoader.getIdeHelper().invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    if (subscriptionList.isEmpty()) {
                                        setMessages(
                                                "Please sign in to import your Azure subscriptions. The credentials in a publish settings file are not sufficient for the web app functionality.");
                                        selectedWebSite = null;
                                        editSubscriptions(true);
                                    } else if (webSiteConfigMap.isEmpty()) {
                                        setMessages("There are no Azure web apps in the imported subscriptions.");
                                        selectedWebSite = null;
                                    } else {
                                        setWebApps(webSiteConfigMap);
                                    }
                                }
                            });
                        }

                        @Override
                        public void onError(@NotNull Throwable throwable) {
                            AzurePlugin.log(throwable.getStackTrace().toString());
                        }

                        private void loadWebSiteConfigurations(final Subscription subscription,
                                final SettableFuture<Void> subscriptionFuture) {
                            try {
                                if (AzureSettings.getSafeInstance(AzurePlugin.project).iswebAppLoaded()) {
                                    webSiteConfigMap = AzureSettings.getSafeInstance(AzurePlugin.project)
                                            .loadWebApps();
                                    subscriptionFuture.set(null);
                                } else {
                                    List<ListenableFuture<Void>> webSpaceFutures = new ArrayList<ListenableFuture<Void>>();
                                    for (final String webSpace : manager
                                            .getResourceGroupNames(subscription.getId())) {
                                        if (cancellationHandle.isCancelled()) {
                                            subscriptionFuture.set(null);
                                            return;
                                        }
                                        final SettableFuture<Void> webSpaceFuture = SettableFuture.create();
                                        DefaultLoader.getIdeHelper().executeOnPooledThread(new Runnable() {
                                            @Override
                                            public void run() {
                                                loadWebSiteConfigurations(subscription, webSpace, webSpaceFuture);
                                            }
                                        });
                                        webSpaceFutures.add(webSpaceFuture);
                                    }
                                    Futures.addCallback(Futures.allAsList(webSpaceFutures),
                                            new FutureCallback<List<Void>>() {
                                                @Override
                                                public void onSuccess(List<Void> voids) {
                                                    subscriptionFuture.set(null);
                                                }

                                                @Override
                                                public void onFailure(Throwable throwable) {
                                                    subscriptionFuture.setException(throwable);
                                                }
                                            });
                                }
                            } catch (AzureCmdException ex) {
                                subscriptionFuture.setException(ex);
                            }
                        }

                        private void loadWebSiteConfigurations(final Subscription subscription,
                                final String webSpace, final SettableFuture<Void> webSpaceFuture) {
                            try {
                                List<ListenableFuture<Void>> webSiteFutures = new ArrayList<ListenableFuture<Void>>();
                                for (final WebSite webSite : manager.getWebSites(subscription.getId(), webSpace)) {
                                    if (cancellationHandle.isCancelled()) {
                                        webSpaceFuture.set(null);
                                        return;
                                    }
                                    final SettableFuture<Void> webSiteFuture = SettableFuture.create();
                                    DefaultLoader.getIdeHelper().executeOnPooledThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            loadWebSiteConfigurations(subscription, webSpace, webSite,
                                                    webSiteFuture);
                                        }
                                    });
                                    webSiteFutures.add(webSiteFuture);
                                }

                                Futures.addCallback(Futures.allAsList(webSiteFutures),
                                        new FutureCallback<List<Void>>() {
                                            @Override
                                            public void onSuccess(List<Void> voids) {
                                                webSpaceFuture.set(null);
                                            }

                                            @Override
                                            public void onFailure(Throwable throwable) {
                                                webSpaceFuture.setException(throwable);
                                            }
                                        });
                            } catch (AzureCmdException ex) {
                                webSpaceFuture.setException(ex);
                            }
                        }

                        private void loadWebSiteConfigurations(final Subscription subscription,
                                final String webSpace, final WebSite webSite,
                                final SettableFuture<Void> webSiteFuture) {
                            WebSiteConfiguration webSiteConfiguration;
                            try {
                                webSiteConfiguration = AzureManagerImpl.getManager().getWebSiteConfiguration(
                                        webSite.getSubscriptionId(), webSite.getWebSpaceName(), webSite.getName());
                            } catch (Throwable ignore) {
                                webSiteConfiguration = new WebSiteConfiguration(webSpace, webSite.getName(),
                                        subscription.getId());
                            }
                            synchronized (lock) {
                                webSiteConfigMap.put(webSite, webSiteConfiguration);
                                AzureSettings.getSafeInstance(AzurePlugin.project).saveWebApps(webSiteConfigMap);
                                AzureSettings.getSafeInstance(AzurePlugin.project).setwebAppLoaded(true);
                            }
                            webSiteFuture.set(null);
                        }
                    });
        } catch (AzureCmdException e) {
            selectedWebSite = null;
            AzurePlugin.log("Error Loading Web Apps Info", e);
        }
    }

    private void setWebApps(@NotNull final Map<WebSite, WebSiteConfiguration> webSiteConfigMap) {
        webSiteList = new ArrayList<WebSite>(webSiteConfigMap.keySet());
        Collections.sort(webSiteList, new Comparator<WebSite>() {
            @Override
            public int compare(WebSite ws1, WebSite ws2) {
                return ws1.getName().compareTo(ws2.getName());
            }
        });

        selectedWebSite = null;

        webSiteJList.setModel(new AbstractListModel() {
            @Override
            public int getSize() {
                return webSiteList.size();
            }

            @Override
            public Object getElementAt(int i) {
                WebSite webSite = webSiteList.get(i);
                WebSiteConfiguration webSiteConfiguration = webSiteConfigMap.get(webSite);

                StringBuilder builder = new StringBuilder(webSite.getName());

                if (!webSiteConfiguration.getJavaVersion().isEmpty()) {
                    builder.append(" (JRE ");
                    builder.append(webSiteConfiguration.getJavaVersion());

                    if (!webSiteConfiguration.getJavaContainer().isEmpty()) {
                        builder.append("; ");
                        builder.append(webSiteConfiguration.getJavaContainer());
                        builder.append(" ");
                        builder.append(webSiteConfiguration.getJavaContainerVersion());
                    }
                    builder.append(")");
                } else {
                    builder.append(" (.NET ");
                    builder.append(webSiteConfiguration.getNetFrameworkVersion());

                    if (!webSiteConfiguration.getPhpVersion().isEmpty()) {
                        builder.append("; PHP ");
                        builder.append(webSiteConfiguration.getPhpVersion());
                    }
                    builder.append(")");
                }
                return builder.toString();
            }
        });

        webSiteJList.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent listSelectionEvent) {
                int index = webSiteJList.getSelectedIndex();
                if (index >= 0 && webSiteList.size() > index) {
                    selectedWebSite = webSiteList.get(index);
                } else {
                    selectedWebSite = null;
                }
            }
        });

        webSiteJList.setCellRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                JLabel jLabel = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected,
                        cellHasFocus);

                Border border = jLabel.getBorder();
                Border margin = new EmptyBorder(0, 2, 0, 2);
                jLabel.setBorder(new CompoundBorder(border, margin));

                if (!isDeployable(webSiteConfigMap, webSiteList, index)) {
                    jLabel.setBackground(list.getBackground());
                    jLabel.setForeground(UIManager.getColor("Label.disabledForeground"));
                }

                return jLabel;
            }
        });

        // select newly created azure web app
        ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
                if (!nameToSelect.isEmpty()) {
                    for (int i = 0; i < webSiteList.size(); i++) {
                        WebSite website = webSiteList.get(i);
                        if (website.getName().equalsIgnoreCase(nameToSelect)) {
                            webSiteJList.setSelectedIndex(i);
                            break;
                        }
                    }
                }
            }
        }, ModalityState.defaultModalityState());
    }

    private static boolean isDeployable(@NotNull Map<WebSite, WebSiteConfiguration> webSiteConfigMap,
            @NotNull List<WebSite> webSiteList, int index) {
        return index >= 0 && webSiteList.size() > index
                && !webSiteConfigMap.get(webSiteList.get(index)).getJavaContainer().isEmpty();
    }

    private void setMessages(String... messages) {
        webSiteJList.setModel(getMessageListModel(messages));
    }

    @NotNull
    private static AbstractListModel getMessageListModel(final String... messages) {
        return new AbstractListModel() {
            @Override
            public int getSize() {
                return messages.length;
            }

            @Override
            public Object getElementAt(int index) {
                return messages[index];
            }
        };
    }

    private void createWebApp() {
        CreateWebSiteForm form = new CreateWebSiteForm(project, webSiteList);
        form.show();

        if (form.isOK()) {
            nameToSelect = form.getWebAppCreated();
            fillList();
        }
    }

    private void editSubscriptions(boolean invokeSignIn) {
        try {
            final ManageSubscriptionPanel manageSubscriptionPanel = new ManageSubscriptionPanel(project, false);
            final DefaultDialogWrapper subscriptionsDialog = new DefaultDialogWrapper(project,
                    manageSubscriptionPanel) {
                @Nullable
                @Override
                protected JComponent createSouthPanel() {
                    return null;
                }

                @Override
                protected JComponent createTitlePane() {
                    return null;
                }
            };
            manageSubscriptionPanel.setDialog(subscriptionsDialog);
            JButton signInBtn = manageSubscriptionPanel.getSignInButton();
            if (invokeSignIn && signInBtn != null && signInBtn.getText().equalsIgnoreCase("Sign In...")) {
                signInBtn.doClick();
            }
            subscriptionsDialog.show();

            subscriptionList = AzureManagerImpl.getManager().getSubscriptionList();
            if (subscriptionList.size() == 0) {
                setMessages(
                        "Please sign in to import your Azure subscriptions. The credentials in a publish settings file are not sufficient for the web app functionality.");
                selectedWebSite = null;
            } else {
                fillList();
            }
        } catch (AzureCmdException e) {
            setMessages("There has been an error while retrieving the configured Azure subscriptions.",
                    "Please retry signing in/importing your Azure subscriptions.");
        }
    }

    public WebSite getSelectedWebSite() {
        return selectedWebSite;
    }
}