com.google.gwt.eclipse.oophm.views.hierarchical.WebAppLaunchView.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.eclipse.oophm.views.hierarchical.WebAppLaunchView.java

Source

/*******************************************************************************
 * Copyright 2011 Google Inc. All Rights Reserved.
 *
 * 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
 *
 * 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.google.gwt.eclipse.oophm.views.hierarchical;

import com.google.gdt.eclipse.core.StatusUtilities;
import com.google.gwt.eclipse.core.preferences.GWTPreferences;
import com.google.gwt.eclipse.oophm.Activator;
import com.google.gwt.eclipse.oophm.DevModeImages;
import com.google.gwt.eclipse.oophm.devmode.DevModeServiceClient;
import com.google.gwt.eclipse.oophm.devmode.DevModeServiceClientManager;
import com.google.gwt.eclipse.oophm.model.BrowserTab;
import com.google.gwt.eclipse.oophm.model.LaunchConfiguration;
import com.google.gwt.eclipse.oophm.model.Log;
import com.google.gwt.eclipse.oophm.model.WebAppDebugModel;
import com.google.gwt.eclipse.oophm.model.WebAppDebugModelEvent;
import com.google.gwt.eclipse.oophm.model.WebAppDebugModelListenerAdapter;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ViewPart;

import java.util.List;

/**
 * A Web Application debug view that allows inspections of launch configurations, browsers and
 * servers.
 */
public class WebAppLaunchView extends ViewPart {
    /**
     * Enumeration used for persisting and restoring the layout state of this view.
     */
    enum LayoutType {
        BREADCRUMB, TREE;

        public static LayoutType toLayoutType(String layoutName) {
            try {
                if (layoutName != null) {
                    return valueOf(layoutName);
                }
            } catch (IllegalArgumentException e) {
                // ignored;
            }

            // Return BREADCRUMB as the default
            return BREADCRUMB;
        }
    }

    /**
     * Action for clearing a log viewer in the current selection.
     */
    private final class ClearLogViewerAction extends Action {
        private ClearLogViewerAction() {
            super("Clear Log Viewer", Activator.getDefault().getImageDescriptor(DevModeImages.CLEAR_LOG));
        }

        @Override
        public void run() {
            ISelection selection = currentLayout.getSelection();
            if (selection.isEmpty()) {
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                if (firstElement instanceof BrowserTab) {
                    BrowserTab browserTab = (BrowserTab) firstElement;
                    browserTab.clearLog();
                }

                // TODO: When we have a server entry, we'll have to clear its logs as
                // well

                clearLogAction.setEnabled(false);
            }
        }
    }

    /**
     * Controls when the ClearLogViewerAction should be enabled/disabled based on the current
     * selection.
     */
    private final class ClearLogViewerEnablementController implements ISelectionChangedListener {

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            ISelection selection = event.getSelection();
            if (selection.isEmpty()) {
                // Empty selection disables the action
                clearLogAction.setEnabled(false);
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                clearLogAction.setEnabled(shouldEnableClearLogAction(firstElement));
            }
        }

        private boolean shouldEnableClearLogAction(Object firstElement) {
            if (firstElement instanceof BrowserTab) {
                Log<?> log = ((BrowserTab) firstElement).getLog();
                return log != null && log.hasDisclosedLogEntries();
            }

            return false;
        }
    }

    /**
     * Action for clearing terminated launches.
     */
    private final class ClearTerminatedLaunchesAction extends Action {
        private ClearTerminatedLaunchesAction() {
            super("Remove all terminated launches",
                    Activator.getDefault().getImageDescriptor(DevModeImages.CLEAR_TERMINATED_LAUNCHES));
        }

        @Override
        public void run() {
            WebAppDebugModel.getInstance().removeTerminatedLaunchesFromModel();

            /*
             * At this point, we know that the view has been notified of the removals of the terminated
             * launches from the model. It is safe to disable the "Clear Terminated Launches" button,
             * because there is no way that the viewer could have been notified about a newly-terminated
             * launch while this method is executing. Notifications occur on the UI thread, and we're
             * currently executing on the UI thread.
             */
            clearTerminatedLaunches.setEnabled(false);
        }
    }

    /**
     * Controls when the {@link ClearTerminatedLaunchesAction} should be enabled/disabled based on the
     * current selection.
     */
    private final class ClearTerminatedLaunchesEnablementController extends WebAppDebugModelListenerAdapter
            implements ISelectionChangedListener {
        public ClearTerminatedLaunchesEnablementController() {
            WebAppDebugModel.getInstance().addWebAppDebugModelListener(this);
        }

        @Override
        public void launchConfigurationTerminated(WebAppDebugModelEvent<LaunchConfiguration> e) {
            Display.getDefault().syncExec(new Runnable() {
                @Override
                public void run() {
                    /*
                     * We execute the runnable synchronously here, because we want to make sure it's safe to
                     * enable the "Clear Terminated Launches" button. If we were to execute this runnable
                     * asynchronously, the enabling may happen after the user actually clicks the
                     * "Clear Terminated Launches" action. (the likelihood of this is very low).
                     */
                    clearTerminatedLaunches.setEnabled(true);
                }
            });
        }

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            ISelection selection = event.getSelection();
            if (selection.isEmpty()) {
                clearTerminatedLaunches.setEnabled(false);
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                clearTerminatedLaunches.setEnabled(shouldEnableAction(firstElement));
            }
        }

        private boolean shouldEnableAction(Object firstElement) {
            WebAppDebugModel model = WebAppDebugModel.getInstance();
            List<LaunchConfiguration> terminatedLaunchConfigurations = model.getTerminatedLaunchConfigurations();
            return terminatedLaunchConfigurations.size() > 0;
        }
    }

    /**
     * Action for restarting a server.
     */
    private final class ReloadServerAction extends Action {
        private ReloadServerAction() {
            super("Reload web server", Activator.getDefault().getImageDescriptor(DevModeImages.RELOAD_WEB_SERVER));
        }

        @Override
        public void run() {
            ISelection selection = currentLayout.getSelection();
            if (selection.isEmpty()) {
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();

                final LaunchConfiguration lc;
                if (firstElement instanceof BrowserTab) {
                    lc = ((BrowserTab) firstElement).getLaunchConfiguration();
                } else if (firstElement instanceof LaunchConfiguration) {
                    lc = (LaunchConfiguration) firstElement;
                } else {
                    lc = null;
                }

                if (lc == null || lc.isTerminated()) {
                    return;
                }

                final DevModeServiceClient client = DevModeServiceClientManager.getInstance().getClient(lc);

                if (client == null) {
                    return;
                }

                reloadServer.setEnabled(false); // ok because we're on the UI thread
                lc.setServerReloading(true);

                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            client.restartWebServer();
                        } catch (Exception e) {
                            Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID,
                                    "Unable to reload the web server.", e));
                            Display.getDefault().asyncExec(new Runnable() {
                                @Override
                                public void run() {
                                    MessageDialog.openError(getSite().getShell(), "Development Mode View",
                                            "Unable to reload the web server. See the Error Log for detals.");
                                }
                            });
                        }
                        lc.setServerReloading(false);

                    }
                });
                t.setName("Restart Web Server Executor Thread");
                t.setDaemon(true);
                t.start();
            }
        }
    }

    /**
     * Controls when the {@link ReloadServerAction} should be enabled/disabled based on the current
     * selection.
     */
    private final class ReloadServerEnablementController extends WebAppDebugModelListenerAdapter
            implements ISelectionChangedListener {

        public ReloadServerEnablementController() {
            WebAppDebugModel.getInstance().addWebAppDebugModelListener(this);
        }

        @Override
        public void launchConfigurationRestartWebServerStatusChanged(WebAppDebugModelEvent<LaunchConfiguration> e) {
            Display.getDefault().asyncExec(new Runnable() {
                @Override
                public void run() {
                    shouldEnableActionBasedOnSelection(currentLayout.getSelection());
                }
            });
        }

        @Override
        public void launchConfigurationTerminated(WebAppDebugModelEvent<LaunchConfiguration> e) {
            Display.getDefault().asyncExec(new Runnable() {
                @Override
                public void run() {
                    shouldEnableActionBasedOnSelection(currentLayout.getSelection());
                }
            });
        }

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            shouldEnableActionBasedOnSelection(event.getSelection());
        }

        private boolean shouldEnableAction(Object firstElement) {
            LaunchConfiguration launchConfiguration = null;
            if (firstElement instanceof BrowserTab) {
                BrowserTab browserTab = (BrowserTab) firstElement;
                launchConfiguration = browserTab.getLaunchConfiguration();
            } else if (firstElement instanceof LaunchConfiguration) {
                launchConfiguration = (LaunchConfiguration) firstElement;
            } else {
                return false;
            }

            return launchConfiguration.hasWebServer() && launchConfiguration.supportsRestartWebServer()
                    && !launchConfiguration.isTerminated() && !launchConfiguration.isServerReloading();
        }

        private void shouldEnableActionBasedOnSelection(ISelection selection) {
            if (selection.isEmpty()) {
                reloadServer.setEnabled(false);
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                reloadServer.setEnabled(shouldEnableAction(firstElement));
            }
        }
    }

    /**
     * Listens for a new launch, and if the preference is set, remove terminated launches.
     */
    private final class RemoveTerminatedLaunchesOnLaunchListener extends WebAppDebugModelListenerAdapter {

        @Override
        public void launchConfigurationLaunched(WebAppDebugModelEvent<LaunchConfiguration> e) {
            Display.getDefault().syncExec(new Runnable() {
                @Override
                @SuppressWarnings("restriction")
                public void run() {
                    if (GWTPreferences.getRemoveTerminatedLaunches()) {
                        clearTerminatedLaunches.run();
                    }
                }
            });
        }

    }

    /**
     * Action for terminating a launch configuration.
     */
    private final class TerminateLaunchAction extends Action {
        public TerminateLaunchAction() {
            super("Terminate Selected Launch",
                    Activator.getDefault().getImageDescriptor(DevModeImages.TERMINATE_LAUNCH));
        }

        @Override
        public void run() {
            ISelection selection = currentLayout.getSelection();
            if (selection.isEmpty()) {
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                LaunchConfiguration launchConfiguration = null;
                if (firstElement instanceof BrowserTab) {
                    BrowserTab browserTab = (BrowserTab) firstElement;
                    launchConfiguration = browserTab.getLaunchConfiguration();
                } else if (firstElement instanceof LaunchConfiguration) {
                    launchConfiguration = (LaunchConfiguration) firstElement;
                } else {
                    return;
                }

                try {
                    launchConfiguration.getLaunch().terminate();
                    terminateLaunchAction.setEnabled(false);
                } catch (DebugException e) {
                    Activator.getDefault().getLog().log(StatusUtilities.newErrorStatus(e, Activator.PLUGIN_ID));
                }
            }
        }
    }

    /**
     * Controls when the TerminateLaunchAction should be enabled/disabled based on the current
     * selection.
     */
    private final class TerminateLaunchEnablementController implements ISelectionChangedListener {

        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            ISelection selection = event.getSelection();
            if (selection.isEmpty()) {
                // Empty selection disables the action
                terminateLaunchAction.setEnabled(false);
                return;
            }

            if (selection instanceof IStructuredSelection) {
                IStructuredSelection structuredSelection = (IStructuredSelection) selection;
                Object firstElement = structuredSelection.getFirstElement();
                terminateLaunchAction.setEnabled(shouldEnableAction(firstElement));
            }
        }

        private boolean shouldEnableAction(Object firstElement) {
            LaunchConfiguration launchConfiguration = null;
            if (firstElement instanceof BrowserTab) {
                BrowserTab browserTab = (BrowserTab) firstElement;
                launchConfiguration = browserTab.getLaunchConfiguration();
            } else if (firstElement instanceof LaunchConfiguration) {
                launchConfiguration = (LaunchConfiguration) firstElement;
            } else {
                return false;
            }

            return !launchConfiguration.isTerminated();
        }
    }

    /**
     * The ID of the view as specified by the extension. Note this is hard-coded since the ID differs
     * from the plugin package name.
     */
    public static final String ID = "com.gwtplugins.gwt.eclipse.DevModeView";

    protected static final Object[] NO_ELEMENTS = new Object[0];

    /**
     * Key used to store this view's layout in this plugin's {@link IDialogSettings}.
     */
    private static final String DIALOG_PROPERTIES_LAYOUT_KEY = WebAppLaunchView.ID + ".layout";

    private BreadcrumbNavigationView breadcrumbLayout;
    private Action clearLogAction;
    private Action clearTerminatedLaunches;
    private ISelectionProvider currentLayout;

    private PageBook pageBook;

    private Action reloadServer;
    private Action switchToBreadcrumbLayoutAction;
    private Action switchToTreeLayoutAction;
    private Action terminateLaunchAction;

    private TreeNavigationView treeLayout;

    /**
     * This is a callback that will allow us to create the viewer and initialize it.
     */
    @Override
    public void createPartControl(Composite parent) {
        createActions();
        addTerminatedLaunchListener();
        createLayouts(parent);
        contributeToActionBars();
        initControls();
    }

    public IToolBarManager getToolbarManager() {
        return getViewSite().getActionBars().getToolBarManager();
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    @Override
    public void setFocus() {
        // TODO: Fill me in
    }

    private void addTerminatedLaunchListener() {
        WebAppDebugModel.getInstance().addWebAppDebugModelListener(new RemoveTerminatedLaunchesOnLaunchListener());
    }

    private void contributeToActionBars() {
        IActionBars bars = getViewSite().getActionBars();
        fillLocalPullDown(bars.getMenuManager());
        fillLocalToolBar(bars.getToolBarManager());
    }

    private void createActions() {

        switchToTreeLayoutAction = new Action("Tree", IAction.AS_RADIO_BUTTON) {
            @Override
            public void run() {
                switchToTreeLayout();
            }
        };

        switchToBreadcrumbLayoutAction = new Action("Breadcrumb", IAction.AS_RADIO_BUTTON) {
            @Override
            public void run() {
                switchToBreadcrumbLayout();
            }
        };

        clearLogAction = new ClearLogViewerAction();
        clearTerminatedLaunches = new ClearTerminatedLaunchesAction();
        reloadServer = new ReloadServerAction();
        terminateLaunchAction = new TerminateLaunchAction();
    }

    private void createLayouts(Composite parent) {
        pageBook = new PageBook(parent, SWT.NONE);

        WebAppDebugModel model = WebAppDebugModel.getInstance();

        treeLayout = new TreeNavigationView(pageBook, SWT.NONE);

        treeLayout.addSelectionChangedListener(new ClearLogViewerEnablementController());
        treeLayout.addSelectionChangedListener(new ClearTerminatedLaunchesEnablementController());
        treeLayout.addSelectionChangedListener(new ReloadServerEnablementController());
        treeLayout.addSelectionChangedListener(new TerminateLaunchEnablementController());

        treeLayout.setInput(model);

        breadcrumbLayout = new BreadcrumbNavigationView(pageBook, SWT.NONE);

        breadcrumbLayout.addSelectionChangedListener(new ClearLogViewerEnablementController());
        breadcrumbLayout.addSelectionChangedListener(new ClearTerminatedLaunchesEnablementController());
        breadcrumbLayout.addSelectionChangedListener(new ReloadServerEnablementController());
        breadcrumbLayout.addSelectionChangedListener(new TerminateLaunchEnablementController());

        breadcrumbLayout.setInput(model);
    }

    private void fillLocalPullDown(IMenuManager manager) {
        MenuManager layoutMenu = new MenuManager("Layout");

        layoutMenu.add(switchToTreeLayoutAction);
        layoutMenu.add(switchToBreadcrumbLayoutAction);

        manager.add(layoutMenu);
    }

    private void fillLocalToolBar(IToolBarManager manager) {
        manager.add(terminateLaunchAction);
        manager.add(clearTerminatedLaunches);
        manager.add(new Separator());
        manager.add(reloadServer);
        manager.add(new Separator());
        manager.add(clearLogAction);
    }

    private IDialogSettings getDialogSettings() {
        return Activator.getDefault().getDialogSettings();
    }

    private void initControls() {
        IDialogSettings dialogSettings = getDialogSettings();
        String layoutName = dialogSettings.get(DIALOG_PROPERTIES_LAYOUT_KEY);
        LayoutType layoutType = LayoutType.toLayoutType(layoutName);
        if (layoutType == LayoutType.BREADCRUMB) {
            switchToBreadcrumbLayout();
        } else {
            switchToTreeLayout();
        }
    }

    private StructuredSelection maybeSelectFirstLaunchConfig() {
        if (WebAppDebugModel.getInstance().getLaunchConfigurations().size() > 0) {
            return new StructuredSelection(WebAppDebugModel.getInstance().getLaunchConfigurations().get(0));
        }

        return null;
    }

    private void switchToBreadcrumbLayout() {
        if (currentLayout == breadcrumbLayout) {
            return;
        }

        ISelection selection = null;
        if (currentLayout == null) {
            // Initializing
            selection = maybeSelectFirstLaunchConfig();
        } else {
            assert (currentLayout == treeLayout);
            selection = treeLayout.getSelection();
        }

        switchToBreadcrumbLayoutAction.setChecked(true);
        switchToTreeLayoutAction.setChecked(false);

        currentLayout = breadcrumbLayout;
        if (selection != null && !selection.isEmpty()) {
            currentLayout.setSelection(selection);
        }

        pageBook.showPage(breadcrumbLayout);
        getDialogSettings().put(DIALOG_PROPERTIES_LAYOUT_KEY, LayoutType.BREADCRUMB.name());
    }

    private void switchToTreeLayout() {
        if (currentLayout == treeLayout) {
            return;
        }

        switchToTreeLayoutAction.setChecked(true);
        switchToBreadcrumbLayoutAction.setChecked(false);

        ISelection selection = null;
        if (currentLayout == null) {
            // Initializing
            selection = maybeSelectFirstLaunchConfig();
        } else {
            assert (currentLayout == breadcrumbLayout);
            selection = breadcrumbLayout.getSelection();
        }

        currentLayout = treeLayout;
        if (selection != null && !selection.isEmpty()) {
            currentLayout.setSelection(selection);
        }

        pageBook.showPage(treeLayout);
        getDialogSettings().put(DIALOG_PROPERTIES_LAYOUT_KEY, LayoutType.TREE.name());
    }

}