cn.dockerfoundry.ide.eclipse.server.ui.internal.editor.ApplicationMasterPart.java Source code

Java tutorial

Introduction

Here is the source code for cn.dockerfoundry.ide.eclipse.server.ui.internal.editor.ApplicationMasterPart.java

Source

/*******************************************************************************
 * Copyright (c) 2012, 2015 Pivotal Software Inc and IBM Corporation 
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of 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.
 *  
 *  Contributors:
 *     Pivotal Software, Inc. - initial API and implementation
 *     Steven Hung, IBM - add accessibility for managing service binding
 ********************************************************************************/
package cn.dockerfoundry.ide.eclipse.server.ui.internal.editor;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.cloudfoundry.client.lib.domain.CloudApplication;
import org.cloudfoundry.client.lib.domain.CloudService;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.DecorationOverlayIcon;
import org.eclipse.jface.viewers.IDecoration;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.SectionPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.wst.server.core.IModule;
import org.eclipse.wst.server.ui.internal.ImageResource;
import org.eclipse.wst.server.ui.internal.ServerLabelProvider;
import org.eclipse.wst.server.ui.internal.view.servers.RemoveModuleAction;
import org.eclipse.wst.server.ui.internal.view.servers.ServersViewDropAdapter;
import org.eclipse.wst.server.ui.internal.wizard.ModifyModulesWizard;

import cn.dockerfoundry.ide.eclipse.server.core.internal.DockerFoundryServer;
import cn.dockerfoundry.ide.eclipse.server.core.internal.DockerApplicationService;
import cn.dockerfoundry.ide.eclipse.server.core.internal.client.DockerFoundryApplicationModule;
import cn.dockerfoundry.ide.eclipse.server.core.internal.debug.DockerFoundryProperties;
import cn.dockerfoundry.ide.eclipse.server.ui.internal.DockerFoundryImages;
import cn.dockerfoundry.ide.eclipse.server.ui.internal.Messages;
import cn.dockerfoundry.ide.eclipse.server.ui.internal.actions.RefreshEditorAction;
import cn.dockerfoundry.ide.eclipse.server.ui.internal.actions.ServiceToApplicationsBindingAction;

/**
 * @author Terry Denney
 * @author Leo Dos Santos
 * @author Steffen Pingel
 * @author Christian Dupuis
 */
@SuppressWarnings("restriction")
public class ApplicationMasterPart extends SectionPart {

    private TableViewer applicationsViewer;

    private final DockerFoundryServer cloudServer;

    private IModule currentModule;

    private final DockerFoundryApplicationsEditorPage editorPage;

    private TableViewer servicesViewer;

    private FormToolkit toolkit;

    private List<DockerApplicationService> services = new ArrayList<DockerApplicationService>();
    //   private boolean provideServices;

    private Section servicesSection;

    public ApplicationMasterPart(DockerFoundryApplicationsEditorPage editorPage, IManagedForm managedForm,
            Composite parent, DockerFoundryServer cloudServer) {
        super(parent, managedForm.getToolkit(), Section.TITLE_BAR | Section.DESCRIPTION);
        this.editorPage = editorPage;
        this.cloudServer = cloudServer;
        this.toolkit = managedForm.getToolkit();
        //      this.provideServices = CloudFoundryBrandingExtensionPoint.getProvideServices(editorPage.getServer()
        //            .getServerType().getId());

        String linksAsString = this.cloudServer.getDockerContainerLinks();
        if (linksAsString != null && linksAsString.length() > 0) {
            StringTokenizer st = new StringTokenizer(linksAsString, ",");
            if (st != null) {
                while (st.hasMoreTokens()) {
                    String token = st.nextToken();
                    String[] s = token.split(":");
                    DockerApplicationService service = new DockerApplicationService();
                    service.setName(s[0]);
                    service.setLinkName(s[1]);
                    services.add(service);
                }
            }
        }
    }

    /**
     * Creates the content of the master part inside the form part. This method
     * is called when the master/details block is created.
     */
    public void createContents() {
        createApplicationsSection();

        createServicesSection();

        //      createRoutesDomainsSection();
    }

    public TableViewer getApplicationsViewer() {
        return applicationsViewer;
    }

    public IModule getCurrentModule() {
        return currentModule;
    }

    private void updateSections() {
        List<DockerApplicationService> services = editorPage.getServices();
        servicesViewer.setInput((services != null) ? services.toArray() : null);
        if (servicesSection != null && !servicesSection.isExpanded()) {
            // If collapsed, expand (e.g. section is collapsed and user adds
            // a new service)
            servicesSection.setExpanded(true);
        }
    }

    public void refreshUI() {

        IStatus status = cloudServer.refreshCloudModules();

        applicationsViewer.setInput(cloudServer.getServerOriginal().getModules());
        // Update the sections regardless of any errors in the modules, as some
        // modules may have no errors
        updateSections();

        if (editorPage != null && !editorPage.isDisposed()) {
            if (!status.isOK()) {
                editorPage.setErrorMessage(status.getMessage());
            } else {
                editorPage.setErrorMessage(null);
            }
        }

    }

    private class ApplicationViewersDropAdapter extends ServersViewDropAdapter {

        public ApplicationViewersDropAdapter(Viewer viewer) {
            super(viewer);
        }

        @Override
        protected Object getCurrentTarget() {
            return editorPage.getServer().getOriginal();
        }

        @Override
        protected Object determineTarget(DropTargetEvent event) {
            return editorPage.getServer();
        }

        @Override
        public boolean performDrop(final Object data) {
            final String jobName = "Deploying application"; //$NON-NLS-1$
            UIJob job = new UIJob(jobName) {

                @Override
                public IStatus runInUIThread(IProgressMonitor monitor) {

                    if (data instanceof IStructuredSelection) {
                        Object modObj = ((IStructuredSelection) data).getFirstElement();
                        IProject prj = null;
                        if (modObj instanceof IProject) {
                            prj = (IProject) modObj;
                        } else if (modObj instanceof IJavaProject) {
                            prj = ((IJavaProject) modObj).getProject();
                        }

                        if (prj != null) {

                            final DockerFoundryServer cloudServer = (DockerFoundryServer) editorPage.getServer()
                                    .getOriginal().loadAdapter(DockerFoundryServer.class, monitor);

                            if (cloudServer != null) {

                                final String moduleName = prj.getName();

                                // First of all, should make sure there is no
                                // CloundApplicationModule
                                // with the same name of the selected project,
                                // otherwise it will cause
                                // the CloundApplicationModule with the same
                                // name and its related remote
                                // application in CF to be deleted.
                                if (cloudServer.getBehaviour().existCloudApplicationModule(moduleName)) {
                                    Display.getDefault().asyncExec(new Runnable() {

                                        public void run() {
                                            MessageDialog.openError(editorPage.getSite().getShell(),
                                                    Messages.ApplicationMasterPart_ERROR_DEPLOY_FAIL_TITLE,
                                                    NLS.bind(Messages.ApplicationMasterPart_ERROR_DEPLOY_FAIL_BODY,
                                                            moduleName));
                                        }

                                    });
                                    return Status.CANCEL_STATUS;
                                }

                                // Make sure parent performs the drop first to
                                // create the IModule. Unsupported modules will
                                // not proceed result in IModule creation
                                // therefore checks on the IProject are not
                                // necessary
                                ApplicationViewersDropAdapter.super.performDrop(data);

                                // Now do a publish AFTER the IModule is
                                // created. If no IModule is created (either
                                // user cancels or project
                                // is not supported), the publish operation will
                                // do nothing.
                                Job job = new Job(jobName) {

                                    @Override
                                    protected IStatus run(IProgressMonitor monitor) {
                                        cloudServer.getBehaviour().publishAdd(moduleName, monitor);
                                        return Status.OK_STATUS;
                                    }

                                };
                                job.setPriority(Job.INTERACTIVE);
                                job.schedule();
                                return Status.OK_STATUS;
                            }
                        }
                    }
                    return Status.CANCEL_STATUS;
                }
            };
            job.schedule();

            return true;
        }
    }

    private void createApplicationsSection() {
        Section section = getSection();
        section.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(section);
        section.setText(Messages.COMMONTXT_APPLICATIONS);
        section.setDescription(Messages.ApplicationMasterPart_TEXT_APP_DESCRIP);

        Composite client = toolkit.createComposite(section);
        client.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(client);
        section.setClient(client);

        Composite headerComposite = toolkit.createComposite(section, SWT.NONE);
        RowLayout rowLayout = new RowLayout();
        rowLayout.marginTop = 0;
        rowLayout.marginBottom = 0;
        headerComposite.setLayout(rowLayout);
        headerComposite.setBackground(null);

        ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
        toolBarManager.createControl(headerComposite);

        applicationsViewer = new TableViewer(toolkit.createTable(client, SWT.NONE));
        applicationsViewer.setContentProvider(new TreeContentProvider());
        applicationsViewer.setLabelProvider(new ServerLabelProvider() {
            @Override
            public Image getImage(Object element) {
                Image image = super.getImage(element);

                if (element instanceof IModule) {
                    IModule module = (IModule) element;
                    DockerFoundryApplicationModule appModule = editorPage.getCloudServer()
                            .getExistingCloudModule(module);
                    if (appModule != null && appModule.getErrorMessage() != null) {
                        return DockerFoundryImages.getImage(new DecorationOverlayIcon(image,
                                DockerFoundryImages.OVERLAY_ERROR, IDecoration.BOTTOM_LEFT));
                    }
                }

                return image;
            }

            @Override
            public String getText(Object element) {
                // This is the WTP module name (usually, it's the workspace
                // project name)
                String moduleName = super.getText(element);

                // However, the user has the option to specify a different name
                // when pushing an app, which is used as the cf app name. If
                // they are different, and the
                // corresponding workspace project is accessible, show both.
                // Otherwise, show the cf app name.

                if (element instanceof IModule) {

                    IModule module = (IModule) element;

                    // Find the corresponding Cloud Foundry-aware application
                    // Module.
                    DockerFoundryApplicationModule appModule = cloudServer
                            .getExistingCloudModule((IModule) element);

                    if (appModule != null) {
                        String cfAppName = appModule.getDeployedApplicationName();

                        if (cfAppName != null) {

                            // Be sure not to show a null WTP module name,
                            // although
                            // that should not be encountered
                            if (moduleName != null && !cfAppName.equals(moduleName)
                                    && DockerFoundryProperties.isModuleProjectAccessible
                                            .testProperty(new IModule[] { module }, cloudServer)) {
                                moduleName = cfAppName + " (" + moduleName + ")"; //$NON-NLS-1$ //$NON-NLS-2$
                            } else {
                                moduleName = cfAppName;
                            }
                        }
                    }
                }

                return moduleName;
            }

        });
        applicationsViewer.setInput(new CloudApplication[0]);
        applicationsViewer.setSorter(new DockerFoundryViewerSorter());

        applicationsViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                IModule module = (IModule) selection.getFirstElement();

                if (currentModule != module) {
                    currentModule = module;
                    getManagedForm().fireSelectionChanged(ApplicationMasterPart.this, selection);
                }
            }
        });
        GridDataFactory.fillDefaults().grab(true, true).hint(250, SWT.DEFAULT)
                .applyTo(applicationsViewer.getControl());

        int ops = DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT;
        Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getTransfer() };
        ApplicationViewersDropAdapter listener = new ApplicationViewersDropAdapter(applicationsViewer);
        applicationsViewer.addDropSupport(ops, transfers, listener);

        // create context menu
        MenuManager menuManager = new MenuManager();
        menuManager.setRemoveAllWhenShown(true);
        menuManager.addMenuListener(new IMenuListener() {

            public void menuAboutToShow(IMenuManager manager) {
                fillApplicationsContextMenu(manager);
            }
        });

        Menu menu = menuManager.createContextMenu(applicationsViewer.getControl());
        applicationsViewer.getControl().setMenu(menu);
        editorPage.getSite().registerContextMenu(menuManager, applicationsViewer);

        Action addRemoveApplicationAction = new Action(Messages.ApplicationMasterPart_TEXT_ADD_REMOVE,
                ImageResource.getImageDescriptor(ImageResource.IMG_ETOOL_MODIFY_MODULES)) {
            @Override
            public void run() {
                ModifyModulesWizard wizard = new ModifyModulesWizard(cloudServer.getServerOriginal());
                WizardDialog dialog = new WizardDialog(getSection().getShell(), wizard);
                dialog.open();
            }
        };
        toolBarManager.add(addRemoveApplicationAction);

        // Fix for STS-2996. Moved from CloudFoundryApplicationsEditorPage
        toolBarManager.add(RefreshEditorAction.getRefreshAction(editorPage, null));
        toolBarManager.update(true);
        section.setTextClient(headerComposite);

        getManagedForm().getToolkit().paintBordersFor(client);
    }

    private void createServicesSection() {
        servicesSection = toolkit.createSection(getSection().getParent(),
                Section.TITLE_BAR | Section.DESCRIPTION | Section.TWISTIE);
        servicesSection.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(servicesSection);
        servicesSection.setText(Messages.COMMONTXT_SERVICES);
        servicesSection.setExpanded(true);
        servicesSection.setDescription(Messages.ApplicationMasterPart_TEXT_SERVICES_DESCRIP);
        // NOTE:Comment out as keeping section collapsed by default causes zero
        // height tables if no services are provided
        // servicesSection.addExpansionListener(new ExpansionAdapter() {
        //
        // @Override
        // public void expansionStateChanged(ExpansionEvent e) {
        // userExpanded = true;
        // }
        // });

        Composite client = toolkit.createComposite(servicesSection);
        client.setLayout(new GridLayout());
        GridDataFactory.fillDefaults().grab(true, true).applyTo(client);
        servicesSection.setClient(client);

        Composite headerComposite = toolkit.createComposite(servicesSection, SWT.NONE);
        RowLayout rowLayout = new RowLayout();
        rowLayout.marginTop = 0;
        rowLayout.marginBottom = 0;
        headerComposite.setLayout(rowLayout);
        headerComposite.setBackground(null);

        ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
        toolBarManager.createControl(headerComposite);

        servicesViewer = new TableViewer(toolkit.createTable(client, SWT.MULTI));
        new ServiceViewerConfigurator().configureViewer(servicesViewer);

        servicesViewer.setContentProvider(new TreeContentProvider());
        servicesViewer.setLabelProvider(new ServicesTreeLabelProvider(servicesViewer) {

            protected Image getColumnImage(CloudService service, ServiceViewColumn column) {
                return null;
            }

        });
        servicesViewer.setSorter(new ServiceViewerSorter(servicesViewer) {

            @Override
            protected int compare(DockerApplicationService service1, DockerApplicationService service2,
                    ServiceViewColumn sortColumn) {

                return super.compare(service1, service2, sortColumn);
            }

        });
        DockerApplicationService[] servicesArray = new DockerApplicationService[this.services.size()];
        this.services.toArray(servicesArray);
        servicesViewer.setInput(servicesArray);
        //      servicesViewer.setInput(this.services);

        GridDataFactory.fillDefaults().grab(true, true).applyTo(servicesViewer.getControl());

        //      Action addServiceAction = new Action(Messages.COMMONTXT_ADD_SERVICE, CloudFoundryImages.NEW_SERVICE) {
        //         @Override
        //         public void run() {
        //            CloudFoundryServiceWizard wizard = new CloudFoundryServiceWizard(cloudServer);
        //            WizardDialog dialog = new WizardDialog(getSection().getShell(), wizard);
        //            wizard.setParent(dialog);
        //            dialog.setPageSize(900, 600);
        //            dialog.setBlockOnOpen(true);
        //            dialog.open();
        //         }
        //      };
        //      toolBarManager.add(addServiceAction);
        //      toolBarManager.update(true);
        servicesSection.setTextClient(headerComposite);

        // create context menu
        //      MenuManager menuManager = new MenuManager();
        //      menuManager.setRemoveAllWhenShown(true);
        //      menuManager.addMenuListener(new IMenuListener() {
        //
        //         public void menuAboutToShow(IMenuManager manager) {
        //            fillServicesContextMenu(manager);
        //         }
        //      });

        //      Menu menu = menuManager.createContextMenu(servicesViewer.getControl());
        //      servicesViewer.getControl().setMenu(menu);
        //      editorPage.getSite().registerContextMenu(menuManager, servicesViewer);

        // Create drag source on the table
        int ops = DND.DROP_COPY;
        Transfer[] transfers = new Transfer[] { LocalSelectionTransfer.getTransfer() };
        DragSourceAdapter listener = new DragSourceAdapter() {
            @Override
            public void dragSetData(DragSourceEvent event) {
                IStructuredSelection selection = (IStructuredSelection) servicesViewer.getSelection();
                event.data = selection.getFirstElement();
                LocalSelectionTransfer.getTransfer().setSelection(selection);
            }

            @Override
            public void dragStart(DragSourceEvent event) {
                if (event.detail == DND.DROP_NONE || event.detail == DND.DROP_DEFAULT) {
                    event.detail = DND.DROP_COPY;
                }
                dragSetData(event);
            }

        };
        servicesViewer.addDragSupport(ops, transfers, listener);

        getManagedForm().getToolkit().paintBordersFor(client);

    }

    private void fillServicesContextMenu(IMenuManager manager) {
        IStructuredSelection selection = (IStructuredSelection) servicesViewer.getSelection();
        if (selection.isEmpty()) {
            return;
        }

        //      manager.add(new DeleteServicesAction(selection, cloudServer.getBehaviour(), editorPage));

        // [87165642] - For now only support service binding/unbinding for one
        // selected
        // service
        if (selection.size() == 1) {
            manager.add(new ServiceToApplicationsBindingAction(selection, cloudServer.getBehaviour(), editorPage));
        }
    }

    private void fillApplicationsContextMenu(IMenuManager manager) {
        IStructuredSelection selection = (IStructuredSelection) applicationsViewer.getSelection();
        if (selection.isEmpty()) {
            return;
        }

        IModule module = (IModule) selection.getFirstElement();
        if (module != null) {
            manager.add(
                    new RemoveModuleAction(getSection().getShell(), editorPage.getServer().getOriginal(), module));

        }
    }

}