com.buglabs.dragonfly.ui.wizards.bugProject.OSGiServiceBindingPage.java Source code

Java tutorial

Introduction

Here is the source code for com.buglabs.dragonfly.ui.wizards.bugProject.OSGiServiceBindingPage.java

Source

/*******************************************************************************
 * Copyright (c) 2006, 2007 Bug Labs, Inc..
 * 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.buglabs.net/legal/epl_license.html
 *******************************************************************************/
package com.buglabs.dragonfly.ui.wizards.bugProject;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.IStreamListener;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamMonitor;
import org.eclipse.debug.core.model.RuntimeProcess;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;

import com.buglabs.dragonfly.BugConnectionManager;
import com.buglabs.dragonfly.DragonflyActivator;
import com.buglabs.dragonfly.model.BaseTreeNode;
import com.buglabs.dragonfly.model.BugConnection;
import com.buglabs.dragonfly.model.BugProjectInfo;
import com.buglabs.dragonfly.model.ServiceDetail;
import com.buglabs.dragonfly.model.ServiceProperty;
import com.buglabs.dragonfly.model.ServicePropertyHelper;
import com.buglabs.dragonfly.ui.Activator;
import com.buglabs.dragonfly.ui.filters.ServiceFilter;
import com.buglabs.dragonfly.ui.launch.BUGSimulatorLaunchShortCut;
import com.buglabs.dragonfly.ui.views.mybugs.MyBugsViewContentProvider;
import com.buglabs.dragonfly.util.BugWSHelper;
import com.buglabs.dragonfly.util.UIUtils;

/**
 * Wizard page that displays currently running BUGs and allows user to include
 * services from a particular BUG in the project
 * 
 * @author akravets and then... bballantine!
 * 
 */
public class OSGiServiceBindingPage extends WizardPage implements IDebugEventSetListener {

    // titles, labels, tooltips, etc
    private static final String BUGLABS_EMULATOR_BUNDLE_NAME = "com.buglabs.bug.emulator";
    private static final String PAGE_NAME = "CodeGenerationPage";
    private static final String PAGE_TITLE = "Other OSGi Services";
    private static final String TARGET_BUG_TITLE = "Target BUG";
    private static final String TARGET_BUG_INSTRUCTIONS = "Select a BUG from the list below to be used as a target";
    private static final String START_VIRTUAL_BUG_LABEL = "Start &BUG Simulator";
    private static final String START_VIRTUAL_BUG_TOOLTIP = "Start BUG Simulator and start consuming its services";
    private static final String REQUIRED_SERVICES_TITLE = "Required Services";

    private static final String NAME_LABEL = "Name";
    private static final String PACKAGE_LABEL = "Package";

    private static final String SELECT_ALL_LABEL = "&Select All";
    private static final String SELECT_ALL_TOOLTIP = "Select all services";
    private static final String DESELECT_ALL_LABEL = "&Deselect All";
    private static final String DESELECT_ALL_TOOLTIP = "Deselect all services";
    private static final String REFRESH_SERVICES_LABEL = "&Refresh Services";
    private static final String REFRESH_SERVICES_TOOLTIP = "Refreshes services definitions provided by the target BUG";
    private static final String SERVICE_DESCRIPTION_LABEL = "Service Description";

    private static final String RELOAD_LIST_WARN_TITLE = "Reloading Services List";
    private static final String RELOAD_LIST_WARN_MESSAGE = "Any selections you've made will be lost.  Would you like to continue?";

    private static final String LAUNCH_VBUG_MESSAGE = "Launch BUG Simulator to select services that this project will consume.";
    private static final String SELECT_BUG_MESSAGE = "Select a BUG from Target BUG List to choose services that this project will consume.";
    private static final String SVCS_INSTRUCTIONS_TEXT = "Selecting a service will add it to the list of services required to run your project.  Double click the service to add required properties.";
    private static final int BUGS_VIEWER_HEIGHT_HINT = 33;
    private static final int SERVICES_GROUP_HEIGHT_HINT = 240;
    private static final int SERVICES_GROUP_WIDTH_HINT = 550;
    private static final int DEPENDENCY_VIEWER_HEIGHT_HINT = 120;
    private static final int SERVICE_DESCRIPTION_AREA_HEIGHT = 33;

    // UI elements
    private TableViewer bugsViewer;
    private CheckboxTableViewer dependencyViewer;
    private CheckboxTableViewer servicePropertiesViewer;
    private Text serviceDescriptionArea;
    private Button btnStartVBUG;
    private Button refreshServiceDefintions;

    // instance vars to keep track of stuff

    // this is used as the input for the service property viewer
    // it helps, keep track of the possible service properties values
    // for a given service (String hash key = service name)
    private Map<String, List<ServicePropertyHelper>> servicePropertyOptionsMap = new HashMap<String, List<ServicePropertyHelper>>();
    private ServiceFilter serviceFilter = new ServiceFilter();
    private BugProjectInfo pinfo;
    private ISelection currentBugSelection = null;
    private String pageMessage = "";

    protected OSGiServiceBindingPage(BugProjectInfo pinfo) {
        super(PAGE_NAME, PAGE_TITLE,
                Activator.getDefault().getImageRegistry().getDescriptor(Activator.IMAGE_COLOR_DIALOG_PROJECT));
        setMessage(pageMessage);
        this.pinfo = pinfo;
    }

    /**
     * Draw all the parts on the wizard page
     */
    public void createControl(Composite parent) {
        Composite mainComposite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(1, false);
        mainComposite.setLayout(layout);

        // this is the list of all the bugs you can see
        createTargetArea(mainComposite);
        // where you choose the services
        createServicesSection(mainComposite);

        setControl(mainComposite);
    }

    /* METHODS FOR DRAWING STUFF IN COMPOSITE */

    /**
     * Creates TableViewer that has all BUGs currently available in MyBUGs view
     * 
     * @param composite
     */
    private void createTargetArea(final Composite parent) {
        Group composite = new Group(parent, SWT.NONE);
        composite.setText(TARGET_BUG_TITLE);
        composite.setLayout(new GridLayout(2, false));

        GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
        gridData.grabExcessHorizontalSpace = true;

        composite.setLayoutData(gridData);

        GridData gdLabel = new GridData(GridData.FILL_HORIZONTAL);
        gdLabel.horizontalSpan = 2;

        Label label = new Label(composite, SWT.NONE);
        label.setText(TARGET_BUG_INSTRUCTIONS);
        label.setLayoutData(gdLabel);

        GridData fillHorizontal = new GridData(GridData.FILL_HORIZONTAL);
        GridData gdViewer = GridDataFactory.createFrom(fillHorizontal).create();
        gdViewer.heightHint = BUGS_VIEWER_HEIGHT_HINT;
        bugsViewer = new TableViewer(composite, SWT.BORDER | SWT.V_SCROLL);
        bugsViewer.getTable().setLayoutData(gdViewer);

        // set up change listener
        bugsViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(final SelectionChangedEvent event) {
                // not sure why this would be the case, but return if nothing there
                if (((BaseTreeNode) bugsViewer.getInput()).getChildren().size() == 0)
                    return;

                // don't do anything if it's the same as the previous selection
                ISelection selection = event.getSelection();
                if (currentBugSelection != null && currentBugSelection.equals(selection))
                    return;

                if (!reloadListDialog(parent.getShell())) {
                    if (currentBugSelection != null)
                        event.getSelectionProvider().setSelection(currentBugSelection);
                    return;
                }

                // Make sure we can connect to the given BUG
                final BugConnection connection = (BugConnection) ((StructuredSelection) event.getSelection())
                        .getFirstElement();
                if (connection == null)
                    return;

                // set the saved currentBugSelection to the selection
                currentBugSelection = selection;

                // prepare to launch refresh services job
                refreshServiceDefintions.setEnabled(true);

                // clear selections
                clearSelections();

                launchRefreshServicesJob(connection);
            }

        });

        bugsViewer.setContentProvider(new MyBugsViewContentProvider() {
            public Object[] getChildren(Object parentElement) {
                if (parentElement instanceof BaseTreeNode) {
                    return ((BaseTreeNode) parentElement).getChildren().toArray();
                }
                return new Object[0];
            }
        });

        bugsViewer.setLabelProvider(new LabelProvider() {
            public String getText(Object element) {
                if (element instanceof BugConnection) {
                    return ((BugConnection) element).getName();
                } else {
                    return super.getText(element);
                }
            }

            public Image getImage(Object element) {
                if (element instanceof BugConnection) {
                    return Activator.getDefault().getImageRegistry().get(Activator.IMAGE_COLOR_UPLOAD);
                }
                return super.getImage(element);
            }
        });

        BaseTreeNode root = (BaseTreeNode) BugConnectionManager.getInstance().getBugConnectionsRoot();
        bugsViewer.setInput(root);

        btnStartVBUG = new Button(composite, SWT.PUSH);
        btnStartVBUG.setText(START_VIRTUAL_BUG_LABEL);
        btnStartVBUG.setToolTipText(START_VIRTUAL_BUG_TOOLTIP);
        GridData gdButton = new GridData();
        gdButton.verticalAlignment = SWT.TOP;
        btnStartVBUG.setLayoutData(gdButton);
        btnStartVBUG.addSelectionListener(((SelectionListener) new StartVBUGSelectionListener()));

        setPageMessage(root.getChildren().size());
    }

    /**
     * Draws the section where you can filter services or select a service based
     * on your selection above
     * 
     * @param mainComposite
     */
    private void createServicesSection(final Composite mainComposite) {
        // set up
        Composite servicesComposite = new Composite(mainComposite, SWT.NONE);
        GridLayout layout = new GridLayout(2, false);
        servicesComposite.setLayout(layout);

        // box that surrounds this section
        Group compServices = new Group(servicesComposite, SWT.NONE);
        compServices.setText(REQUIRED_SERVICES_TITLE);
        GridData gdServices = new GridData(GridData.FILL_BOTH);
        gdServices.horizontalSpan = 2;
        gdServices.heightHint = SERVICES_GROUP_HEIGHT_HINT;
        gdServices.widthHint = SERVICES_GROUP_WIDTH_HINT;
        gdServices.grabExcessHorizontalSpace = true;
        compServices.setLayoutData(gdServices);
        compServices.setLayout(new GridLayout(3, false));

        GridData gdFillH = new GridData(GridData.FILL_HORIZONTAL);
        servicesComposite.setLayoutData(gdFillH);
        GridData gdFillBoth = GridDataFactory.createFrom(gdFillH).create();
        gdFillBoth.horizontalSpan = layout.numColumns;

        Label instructionsLabel = new Label(compServices, SWT.WRAP);
        instructionsLabel.setLayoutData(gdFillBoth);
        instructionsLabel.setText(SVCS_INSTRUCTIONS_TEXT);

        // text box for services filtering
        Text txtFilter = new Text(compServices, SWT.BORDER);
        txtFilter.setLayoutData(gdFillBoth);
        txtFilter.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                String filter = ((Text) e.widget).getText();
                filter = filter.replaceAll("\\*", ".*");
                serviceFilter.setPattern("(?i).*" + filter + ".*",
                        Arrays.asList(dependencyViewer.getCheckedElements()));
                dependencyViewer.refresh();
            }
        });

        // table with list of services to choose from
        Table modulesTable = new Table(compServices, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.FULL_SELECTION);
        modulesTable.setHeaderVisible(true);
        modulesTable.setLinesVisible(true);
        TableColumn col1 = new TableColumn(modulesTable, SWT.NONE);
        col1.setText(NAME_LABEL);
        TableColumn col2 = new TableColumn(modulesTable, SWT.NONE);
        col2.setText(PACKAGE_LABEL);
        TableLayout tableLayout = new TableLayout();
        tableLayout.addColumnData(new ColumnWeightData(90));
        tableLayout.addColumnData(new ColumnWeightData(120));
        modulesTable.setLayout(tableLayout);

        // viewer for handling service dependency selection
        dependencyViewer = new CheckboxTableViewer(modulesTable);
        GridData viewerData = new GridData(GridData.FILL_BOTH);
        viewerData.horizontalSpan = layout.numColumns;
        viewerData.heightHint = DEPENDENCY_VIEWER_HEIGHT_HINT;
        dependencyViewer.getControl().setLayoutData(viewerData);
        dependencyViewer.setContentProvider(new ModulesContentProvider());
        dependencyViewer.setLabelProvider(new ModulesLabelProvider());
        dependencyViewer.setSorter(new ViewerSorter());
        dependencyViewer.addFilter(serviceFilter);

        dependencyViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                // return if null event
                if (event == null)
                    return;
                ISelection selection = event.getSelection();

                // return if not IStructuredSelection
                if (!(selection instanceof IStructuredSelection))
                    return;
                String selectedService = (String) ((IStructuredSelection) selection).getFirstElement();

                openServicePropertySelectorDialog(mainComposite.getShell(), selectedService, false);
            }
        });

        dependencyViewer.addCheckStateListener(new ICheckStateListener() {
            public void checkStateChanged(CheckStateChangedEvent event) {
                if (event == null)
                    return;
                String selectedService = (String) event.getElement();
                if (selectedService == null)
                    return;

                // update the services list w/ new checked item
                updateModel();
            }
        });

        dependencyViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                // return if null event
                if (event == null)
                    return;
                ISelection selection = event.getSelection();

                // return if not IStructuredSelection
                if (!(selection instanceof IStructuredSelection))
                    return;
                String selectedService = (String) ((IStructuredSelection) selection).getFirstElement();

                // return if selectedService is null
                if (selectedService == null)
                    return;

                String descr = Activator.getServiceDescription(selectedService.trim());
                serviceDescriptionArea.setText(descr);
            }
        });

        Composite buttonComposite = new Composite(compServices, SWT.NONE);
        GridData buttonData = new GridData(GridData.FILL_VERTICAL);
        buttonData.verticalSpan = 3;
        buttonComposite.setLayoutData(buttonData);
        RowLayout buttonLayout = new RowLayout(SWT.VERTICAL);
        buttonLayout.fill = true;
        //buttonLayout.pack = false;
        buttonComposite.setLayout(buttonLayout);

        Button btnSelectAll = new Button(buttonComposite, SWT.PUSH);
        btnSelectAll.setText(SELECT_ALL_LABEL);
        btnSelectAll.setToolTipText(SELECT_ALL_TOOLTIP);
        btnSelectAll.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {/*unused here*/
            }

            public void widgetSelected(SelectionEvent e) {
                dependencyViewer.setAllChecked(true);
                updateModel();
            }
        });

        Button btnDeselectAll = new Button(buttonComposite, SWT.PUSH);
        btnDeselectAll.setText(DESELECT_ALL_LABEL);
        btnDeselectAll.setToolTipText(DESELECT_ALL_TOOLTIP);
        btnDeselectAll.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {/*unused here*/
            }

            public void widgetSelected(SelectionEvent e) {
                dependencyViewer.setAllChecked(false);
                updateModel();
            }
        });

        // refresh services button
        refreshServiceDefintions = new Button(buttonComposite, SWT.PUSH);
        refreshServiceDefintions.setText(REFRESH_SERVICES_LABEL);
        refreshServiceDefintions.setToolTipText(REFRESH_SERVICES_TOOLTIP);
        refreshServiceDefintions.setEnabled(false);
        refreshServiceDefintions.addSelectionListener(new SelectionListener() {
            public void widgetDefaultSelected(SelectionEvent e) {/*unused here*/
            }

            public void widgetSelected(SelectionEvent e) {
                final BugConnection connection = (BugConnection) ((StructuredSelection) bugsViewer.getSelection())
                        .getFirstElement();

                // if no connection, show error and return
                if (connection == null) {
                    UIUtils.giveVisualInformation("Please select target BUG to refresh");
                    return;
                }

                // warn user things are going to get cleared
                if (!reloadListDialog(mainComposite.getShell()))
                    return;

                // clear pinfo's selections
                clearSelections();

                // must be connection, kick off job
                launchRefreshServicesJob(connection);
            }
        });

        // set up service description area
        serviceDescriptionArea = new Text(compServices, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
        GridData descData = new GridData(GridData.FILL_BOTH);
        descData.heightHint = SERVICE_DESCRIPTION_AREA_HEIGHT;
        descData.horizontalSpan = 2;
        serviceDescriptionArea.setLayoutData(descData);
        serviceDescriptionArea.setEditable(false);
        serviceDescriptionArea.setForeground(compServices.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
        serviceDescriptionArea.setText(SERVICE_DESCRIPTION_LABEL);

    }

    /* HELPER METHODS */

    /**
     * Clear stuff in pinfo and stuff in dependencyViewer
     */
    private void clearSelections() {
        // clear pinfo's selections
        pinfo.getServicePropertyHelperMap().clear();
        pinfo.getOSGiServices().clear();
        dependencyViewer.setAllChecked(false);
    }

    /**
     * Warn the user that current selections will be cleared
     * 
     * @param shell
     * @return
     */
    private boolean reloadListDialog(Shell shell) {
        // if we switch to another bug, our settings will be lost!
        if (pinfo.getOSGiServices() == null || pinfo.getOSGiServices().size() < 1)
            return true;

        return MessageDialog.openConfirm(shell, RELOAD_LIST_WARN_TITLE, RELOAD_LIST_WARN_MESSAGE);
    }

    /**
     * Opens the selector dialog that lets us choose service properties for
     * filtering
     * 
     */
    private void openServicePropertySelectorDialog(Shell shell, String selectedService,
            boolean clearCheckedOnCancel) {
        /* TODO - Make sure this works, this is for 1.5 SDK, R1.4.3 of BUG */
        if (servicePropertyOptionsMap.containsKey(selectedService)
                && servicePropertyOptionsMap.get(selectedService) != null
                && servicePropertyOptionsMap.get(selectedService).size() > 0) {
            Dialog d = new ServicePropertySelectorDialog(shell, selectedService,
                    (List<ServicePropertyHelper>) servicePropertyOptionsMap.get(selectedService), pinfo);
            if (d.open() == Dialog.CANCEL && clearCheckedOnCancel) {
                dependencyViewer.setChecked(selectedService, false);
            }
        }

    }

    /**
     * Sets up and kicks off a job to list services provided by connected BUG
     */
    private void launchRefreshServicesJob(BugConnection connection) {
        IJobManager manager = Job.getJobManager();
        String jobFamily = "family-" + connection.getName(); //$NON-NLS-1$
        Job[] jobs = manager.find(jobFamily);

        // TODO - this was commented out, dunno why
        servicePropertyOptionsMap.clear();

        // start a job only if a job within this family has not been started already.
        if (jobs.length == 0) {
            GetServicesJob job = new GetServicesJob("Getting services for " + connection.getName(), connection,
                    jobFamily);
            job.schedule();
        }
    }

    /**
     * Sets the page message based on size
     * 
     * @param size
     */
    private void setPageMessage(int size) {
        if (size == 0)
            setMessage(LAUNCH_VBUG_MESSAGE);
        else
            setMessage(SELECT_BUG_MESSAGE);
    }

    /**
     * Get ServiceDetail List from bug (via WSHelper) and turn into a Map that
     * makes things easier to display
     * 
     * @param bugConnection
     * @param monitor
     */
    private void populateServiceList(final BugConnection bugConnection, IProgressMonitor monitor) {
        try {
            List<ServiceDetail> details = BugWSHelper.getAllServiceDetails(bugConnection.getProgramURL());

            // Older BUGs don't have service details XML
            if (details == null || details.size() < 1) {
                List<String> services = BugWSHelper.getAllServices(bugConnection.getProgramURL());
                details = new ArrayList<ServiceDetail>();
                for (String service : services) {
                    details.add(new ServiceDetail(service, new ArrayList<ServiceProperty>()));
                }
            }

            // clear the map before adding stuff
            servicePropertyOptionsMap.clear();

            List<ServiceProperty> properties;
            for (ServiceDetail detail : details) {
                properties = detail.getServiceProperties();
                Collections.sort(properties);
                if (!servicePropertyOptionsMap.containsKey(detail.getServiceName()))
                    servicePropertyOptionsMap.put(detail.getServiceName(),
                            ServicePropertyHelper.createHelperList(properties));
                else
                    servicePropertyOptionsMap.get(detail.getServiceName())
                            .addAll(ServicePropertyHelper.createHelperList(properties));
            }

            setInputForDependencyViewer();
        } catch (final Exception e1) {
            UIUtils.handleNonvisualError("Failed to connect to BUG", e1);
            servicePropertyOptionsMap.clear();
            setInputForDependencyViewer();
            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                public void run() {
                    OSGiServiceBindingPage.this.setErrorMessage("An error occured while connecting to "
                            + bugConnection.getName() + ": " + e1.getMessage());
                }
            });
        }
    }

    /**
     * Freshen the model based on the viewer.
     */
    private void updateModel() {
        List checkedServices = Arrays.asList(dependencyViewer.getCheckedElements());
        pinfo.getOSGiServices().clear();
        pinfo.getOSGiServices().addAll(checkedServices);
    }

    /**
     * Called to set the input for the dependencyViewer component
     */
    private void setInputForDependencyViewer() {
        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
            public void run() {
                dependencyViewer.setInput(servicePropertyOptionsMap);
            }
        });
    }

    /* INNER CLASSES */

    class ModulesContentProvider implements IStructuredContentProvider {
        public Object[] getElements(Object input) {
            if (input instanceof Map) {
                return ((Map) input).keySet().toArray();
            }
            return null;
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            // don't need to hang onto input for this example, so do nothing
        }

        public void dispose() {
        }
    }

    class ModulesLabelProvider extends LabelProvider implements ITableLabelProvider {
        private final static String DELIM = "."; //$NON-NLS-1$

        public String getColumnText(Object element, int columnIndex) {
            String casted = (String) element;
            switch (columnIndex) {
            case 0:
                return casted.substring(casted.lastIndexOf(DELIM) + 1, casted.length());
            case 1:
                return casted.substring(0, casted.lastIndexOf(DELIM));
            default:
                return "";
            }
        }

        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }
    }

    /**
     * Private inner class to handle clicking of "Lauch BUG Simulator" button
     * 
     * Broken out into private innner class (instead of anonymous class) to make
     * the code easier to read.
     * 
     * 
     */
    private class StartVBUGSelectionListener implements SelectionListener {
        public static final String TYPE = "type";
        public static final String VIRTUAL_BUG = "VIRTUAL_BUG";

        /**
         * Empty
         */
        public void widgetDefaultSelected(SelectionEvent e) {
        }

        /**
         * Selected the Launch BUG Simulator button
         */
        public synchronized void widgetSelected(SelectionEvent e) {
            btnStartVBUG.setEnabled(false);
            btnStartVBUG.getDisplay().syncExec(new Runnable() {
                public void run() {
                    // Reset this global flag - fixes defect 322
                    DragonflyActivator.getDefault().setVirtualBugRemovedByTerminate(false);

                    BUGSimulatorLaunchShortCut virtualBugLaunchShortcut = new BUGSimulatorLaunchShortCut();
                    virtualBugLaunchShortcut.setDiscoveryMode(true);
                    IProcess[] processes = null;
                    try {
                        processes = virtualBugLaunchShortcut.launch(ILaunchManager.RUN_MODE).getProcesses();
                    } catch (CoreException e) {
                        Activator.getDefault().getLog().log(new Status(IStatus.ERROR, DragonflyActivator.PLUGIN_ID,
                                IStatus.OK, "Failure launching BUG Simulator", e));
                    }
                    if (processes == null || processes.length < 1)
                        return;

                    processes[0].setAttribute(TYPE, VIRTUAL_BUG);
                    processes[0].getStreamsProxy().getOutputStreamMonitor()
                            .addListener(new ProcessStreamListener());

                    // if we got to here w/o throwing an exception, the assumption is the
                    // BUG Simulator is launching, however, it takes a few seconds, so delay
                    // creation of connection for 3 seconds
                    new Timer().schedule(new TimerTask() {
                        public void run() {
                            BugConnectionManager.getInstance().addNewVirtualBugConnection();
                        }
                    }, 3000);
                }
            });

            btnStartVBUG.setEnabled(true);
        }

        /**
         * internal helper class to keep things clean
         * 
         */
        private class ProcessStreamListener implements IStreamListener {
            private int cnt = 0;

            public void streamAppended(String text, IStreamMonitor monitor) {
                if (text.indexOf(BUGLABS_EMULATOR_BUNDLE_NAME) == -1)
                    return;
                cnt++;
                if (cnt == 2) {
                    PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                        public void run() {
                            btnStartVBUG.setEnabled(true);
                        }
                    });
                }
            }
        }

    }

    /**
     * Job that retrieves services for a connection
     * 
     * @author akravets
     * 
     */
    private class GetServicesJob extends Job {

        private BugConnection connection;
        private String family;

        public GetServicesJob(String name, BugConnection connection, String family) {
            super(name);
            this.connection = connection;
            this.family = family;
        }

        protected IStatus run(IProgressMonitor monitor) {
            monitor.beginTask("Trying to connect to BUG", IProgressMonitor.UNKNOWN);
            if (connection != null) {
                monitor.beginTask("Retrieving services for " + connection.getName(), IProgressMonitor.UNKNOWN);
                populateServiceList(connection, monitor);
                monitor.done();
            }
            return Status.OK_STATUS;
        }

        public boolean belongsTo(Object family) {
            return this.family.equals(family);
        }
    }

    /* 
     * The next two methods handle removing a BUG Simulator launched from the code generation page, 
     * This code was hastily copied from LaunchVirtualBugAction -- Couldn't figure out a quick way to keep DRY.
     * 
     * First method satisfies implementation of IDebugEventSetListener
     */

    /**
     * 
     * Pick up a BUG Simulator debug event
     */
    public void handleDebugEvents(DebugEvent[] events) {
        for (int i = 0; i < events.length; i++) {
            if (events[i].getSource() instanceof RuntimeProcess) {
                String type = ((RuntimeProcess) events[i].getSource())
                        .getAttribute(StartVBUGSelectionListener.TYPE);
                if (type != null && type.equals(StartVBUGSelectionListener.VIRTUAL_BUG)) {
                    handleVirtualBugEvent(events[i]);
                }
            }
        }
    }

    /**
     * Handle the BUG Simulator event. right now just removing the vbug
     * connection on TERMINATE event
     * 
     * @param event
     */
    private void handleVirtualBugEvent(DebugEvent event) {
        if (event.getKind() == DebugEvent.TERMINATE) {
            if (BugConnectionManager.getInstance().removeVirtualBugConnection()) {
                DragonflyActivator activator = DragonflyActivator.getDefault();
                if (activator != null) {
                    activator.setVirtualBugRemovedByTerminate(true);
                }
            }
        }
    }

}