org.eclipse.pde.internal.runtime.registry.RegistryBrowser.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.pde.internal.runtime.registry.RegistryBrowser.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2013 IBM Corporation and others.
 * 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 211127
 *******************************************************************************/
package org.eclipse.pde.internal.runtime.registry;

import java.util.*;
import java.util.List;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.runtime.*;
import org.eclipse.pde.internal.runtime.registry.model.*;
import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.osgi.framework.BundleException;

public class RegistryBrowser extends ViewPart {

    private class GroupByAction extends Action {
        private int actionGroupBy;

        public GroupByAction(String name, int groupBy) {
            super(name, AS_RADIO_BUTTON);
            this.actionGroupBy = groupBy;
        }

        public void run() {
            if (isChecked()) {
                fMemento.putInteger(GROUP_BY, actionGroupBy);
                // refreshAction takes into account checked state of fShowExtensionsOnlyAction
                // (via updateItems(true)
                fRefreshAction.run();
            }
        }
    }

    public static final String SHOW_RUNNING_PLUGINS = "RegistryView.showRunning.label"; //$NON-NLS-1$
    public static final String SHOW_ADVANCED_MODE = "RegistryView.showAdvancedMode.label"; //$NON-NLS-1$
    public static final String GROUP_BY = "RegistryView.groupBy"; //$NON-NLS-1$ 
    public static final String SHOW_DISABLED_MODE = "RegistryView.showDisabledMode.label"; //$NON-NLS-1$

    public static final int BUNDLES = 0;
    public static final int EXTENSION_REGISTRY = 1;
    public static final int SERVICES = 2;

    private FilteredTree fFilteredTree;
    private TreeViewer fTreeViewer;
    private IMemento fMemento;

    private RegistryModel model;
    private ModelChangeListener listener;
    private Job initializeModelJob;

    private RegistryBrowserContentProvider fContentProvider;
    private RegistryBrowserLabelProvider fLabelProvider;

    private static final int REFRESH_DELAY = 50;
    private long lastRefresh = 0;
    private Thread refreshThread;

    // menus and action items
    private Action fRefreshAction;
    private Action fShowPluginsAction;
    private Action fCollapseAllAction;
    private Action fShowAdvancedOperationsAction;
    private Action fGroupByBundlesAction;
    private Action fGroupByExtensionPointsAction;
    private Action fGroupByServicesAction;
    private Action fShowDisabledAction;
    private Action fCopyAction;

    // advanced actions
    private Action fStartAction;
    private Action fStopAction;
    private Action fEnableAction;
    private Action fDisableAction;
    private Action fDiagnoseAction;

    private Clipboard fClipboard;

    private DrillDownAdapter fDrillDownAdapter;
    private ViewerFilter fActiveFilter = new ViewerFilter() {
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            if (element instanceof ExtensionPoint)
                element = Platform.getBundle(((ExtensionPoint) element).getNamespaceIdentifier());
            else if (element instanceof Extension)
                element = Platform.getBundle(((Extension) element).getNamespaceIdentifier());
            if (element instanceof Bundle)
                return ((Bundle) element).getState() == Bundle.ACTIVE;
            return true;
        }
    };

    private ViewerFilter fDisabledFilter = new ViewerFilter() {
        public boolean select(Viewer viewer, Object parentElement, Object element) {
            if (element instanceof Bundle) {
                return !((Bundle) element).isEnabled();
            }
            return false;
        }
    };

    /*
     * customized DrillDownAdapter which modifies enabled state of showing active/inactive
     * plug-ins action - see Bug 58467
     */
    class RegistryDrillDownAdapter extends DrillDownAdapter {
        public RegistryDrillDownAdapter(TreeViewer tree) {
            super(tree);
        }

        public void goInto() {
            super.goInto();
            fShowPluginsAction.setEnabled(!canGoHome());
            fShowDisabledAction.setEnabled(!canGoHome());
        }

        public void goBack() {
            super.goBack();
            fShowPluginsAction.setEnabled(!canGoHome());
            fShowDisabledAction.setEnabled(!canGoHome());
        }

        public void goHome() {
            super.goHome();
            fShowPluginsAction.setEnabled(!canGoHome());
            fShowDisabledAction.setEnabled(!canGoHome());
        }

        public void goInto(Object newInput) {
            super.goInto(newInput);
            fShowPluginsAction.setEnabled(!canGoHome());
            fShowDisabledAction.setEnabled(!canGoHome());
        }
    }

    private void initializeModel() {
        model = RegistryModelFactory.getRegistryModel("local"); //$NON-NLS-1$
        fTreeViewer.setInput(model);
        listener = new RegistryBrowserModelChangeListener(RegistryBrowser.this);
        model.addModelChangeListener(listener);

        initializeModelJob = new Job(PDERuntimeMessages.RegistryBrowser_InitializingView) {
            public IStatus run(IProgressMonitor monitor) {
                model.connect(monitor, true);
                initializeModelJob = null;
                return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
            }
        };
        initializeModelJob.schedule();
    }

    public void init(IViewSite site, IMemento memento) throws PartInitException {
        super.init(site, memento);
        if (memento == null)
            this.fMemento = XMLMemento.createWriteRoot("REGISTRYVIEW"); //$NON-NLS-1$
        else
            this.fMemento = memento;
        initializeMemento();
    }

    private void initializeMemento() {
        // show all bundles by default (i.e. not just activated ones)
        if (fMemento.getString(SHOW_RUNNING_PLUGINS) == null)
            fMemento.putString(SHOW_RUNNING_PLUGINS, "false"); //$NON-NLS-1$
        if (fMemento.getInteger(GROUP_BY) == null)
            fMemento.putInteger(GROUP_BY, BUNDLES);
        if (fMemento.getString(SHOW_DISABLED_MODE) == null)
            fMemento.putString(SHOW_DISABLED_MODE, "false"); //$NON-NLS-1$

        // default to not showing advanced options to users
        if (fMemento.getString(SHOW_ADVANCED_MODE) == null)
            fMemento.putString(SHOW_ADVANCED_MODE, "false"); //$NON-NLS-1$
    }

    public void dispose() {
        if (initializeModelJob != null) {
            initializeModelJob.cancel();
        }

        model.disconnect();
        model.removeModelChangeListener(listener);
        if (fClipboard != null) {
            fClipboard.dispose();
        }
        super.dispose();
    }

    public void createPartControl(Composite parent) {
        // create the sash form that will contain the tree viewer & text viewer
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginHeight = layout.marginWidth = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        makeActions();
        createTreeViewer(composite);
        hookDoubleClickAction();
        fClipboard = new Clipboard(fTreeViewer.getTree().getDisplay());
        fillToolBar();
    }

    private void createTreeViewer(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginHeight = layout.marginWidth = 0;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));

        fFilteredTree = new RegistryFilteredTree(this, composite, SWT.MULTI, new PatternFilter());

        fFilteredTree.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
        Tree tree = fFilteredTree.getViewer().getTree();
        GridData gd = new GridData(GridData.FILL_BOTH);
        fFilteredTree.setLayoutData(gd);
        fTreeViewer = fFilteredTree.getViewer();
        fContentProvider = new RegistryBrowserContentProvider(this);
        fTreeViewer.setContentProvider(fContentProvider);
        fLabelProvider = new RegistryBrowserLabelProvider(this);
        fTreeViewer.setLabelProvider(fLabelProvider);
        fTreeViewer.setUseHashlookup(true);
        fTreeViewer.setComparator(new ViewerComparator() {
            public int compare(Viewer viewer, Object e1, Object e2) {
                // let Comparables compare themselves
                if (e1 instanceof Comparable && e2 instanceof Comparable && e1.getClass().equals(e2.getClass())) {
                    Comparable c1 = (Comparable) e1;
                    Comparable c2 = (Comparable) e2;

                    return c1.compareTo(c2);
                }

                if (e1 instanceof Folder && e2 instanceof Folder)
                    return ((Folder) e1).getId() - ((Folder) e2).getId();
                if (e1 instanceof Bundle && e2 instanceof Bundle) {
                    e1 = ((Bundle) e1).getSymbolicName();
                    e2 = ((Bundle) e2).getSymbolicName();
                }
                return super.compare(viewer, e1, e2);
            }
        });
        if (fShowPluginsAction.isChecked())
            fTreeViewer.addFilter(fActiveFilter);

        if (fShowDisabledAction.isChecked())
            fTreeViewer.addFilter(fDisabledFilter);

        initializeModel();

        PlatformUI.getWorkbench().getHelpSystem().setHelp(fTreeViewer.getControl(), IHelpContextIds.REGISTRY_VIEW);

        getViewSite().setSelectionProvider(fTreeViewer);

        MenuManager popupMenuManager = new MenuManager();
        IMenuListener listener = new IMenuListener() {
            public void menuAboutToShow(IMenuManager mng) {
                fillContextMenu(mng);
            }
        };
        popupMenuManager.setRemoveAllWhenShown(true);
        popupMenuManager.addMenuListener(listener);
        Menu menu = popupMenuManager.createContextMenu(tree);
        tree.setMenu(menu);
    }

    private void hookDoubleClickAction() {
        fTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
                if (selection.size() == 1) {
                    Object obj = selection.getFirstElement();
                    if (obj instanceof Bundle)
                        ManifestEditor.openPluginEditor(((Bundle) obj).getSymbolicName());
                }
            }
        });
    }

    private void fillToolBar() {
        fDrillDownAdapter = new RegistryDrillDownAdapter(fTreeViewer);
        IActionBars bars = getViewSite().getActionBars();
        bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
        IToolBarManager mng = bars.getToolBarManager();
        fDrillDownAdapter.addNavigationActions(mng);
        mng.add(fRefreshAction);
        mng.add(new Separator());
        mng.add(fCollapseAllAction);
        IMenuManager mgr = bars.getMenuManager();
        IMenuManager manager = new MenuManager(PDERuntimeMessages.RegistryBrowser_GroupBy);
        manager.add(fGroupByBundlesAction);
        manager.add(fGroupByExtensionPointsAction);
        manager.add(fGroupByServicesAction);
        mgr.add(manager);
        mgr.add(new Separator());
        mgr.add(fShowPluginsAction);
        mgr.add(fShowDisabledAction);
        mgr.add(new Separator());
        mgr.add(fShowAdvancedOperationsAction);

    }

    private void fillContextMenu(IMenuManager manager) {
        manager.add(fRefreshAction);
        manager.add(new Separator());
        manager.add(fCopyAction);
        manager.add(new Separator());
        fDrillDownAdapter.addNavigationActions(manager);
        manager.add(new Separator());
        // check if we should enable advanced actions
        if (fShowAdvancedOperationsAction.isChecked() && isBundleSelected()) {
            // control bundle state actions
            if (selectedBundlesStopped())
                manager.add(fStartAction);
            if (selectedBundlesStarted())
                manager.add(fStopAction);

            if (getSelectedBundles().size() == 1)
                manager.add(fDiagnoseAction);

            // security related actions
            if (selectedBundlesDisabled())
                manager.add(fEnableAction);
            if (selectedBundlesEnabled())
                manager.add(fDisableAction);
        }

        manager.add(new Separator());
        manager.add(fShowPluginsAction);
        manager.add(fShowDisabledAction);
        manager.add(new Separator());
        manager.add(fShowAdvancedOperationsAction);
    }

    public void saveState(IMemento memento) {
        if (memento == null || fMemento == null || fTreeViewer == null)
            return;
        fMemento.putString(SHOW_RUNNING_PLUGINS, Boolean.toString(fShowPluginsAction.isChecked()));
        fMemento.putString(SHOW_DISABLED_MODE, Boolean.toString(fShowDisabledAction.isChecked()));
        fMemento.putBoolean(SHOW_ADVANCED_MODE, fShowAdvancedOperationsAction.isChecked());
        memento.putMemento(fMemento);
    }

    public void setFocus() {
        Text filterText = fFilteredTree.getFilterControl();
        if (filterText != null) {
            filterText.setFocus();
        }
    }

    /*
     * toolbar and context menu actions
     */
    private void makeActions() {
        fRefreshAction = new Action("refresh") { //$NON-NLS-1$
            public void run() {
                BusyIndicator.showWhile(fTreeViewer.getTree().getDisplay(), new Runnable() {
                    public void run() {
                        refresh(fTreeViewer.getInput());
                    }
                });
            }
        };
        fRefreshAction.setText(PDERuntimeMessages.RegistryView_refresh_label);
        fRefreshAction.setToolTipText(PDERuntimeMessages.RegistryView_refresh_tooltip);
        fRefreshAction.setImageDescriptor(PDERuntimePluginImages.DESC_REFRESH);
        fRefreshAction.setDisabledImageDescriptor(PDERuntimePluginImages.DESC_REFRESH_DISABLED);

        fShowPluginsAction = new Action(PDERuntimeMessages.RegistryView_showRunning_label) {
            public void run() {
                if (fShowPluginsAction.isChecked()) {
                    fTreeViewer.addFilter(fActiveFilter);
                } else {
                    fTreeViewer.removeFilter(fActiveFilter);
                }
                updateTitle();
            }
        };
        fShowPluginsAction.setChecked(fMemento.getString(SHOW_RUNNING_PLUGINS).equals("true")); //$NON-NLS-1$

        fShowDisabledAction = new Action(PDERuntimeMessages.RegistryView_showDisabled_label) {
            public void run() {
                if (fShowDisabledAction.isChecked()) {
                    fTreeViewer.addFilter(fDisabledFilter);
                } else {
                    fTreeViewer.removeFilter(fDisabledFilter);
                }
                updateTitle();
            }
        };
        fShowDisabledAction.setChecked(fMemento.getString(SHOW_DISABLED_MODE).equals("true")); //$NON-NLS-1$

        fCopyAction = new Action(PDERuntimeMessages.RegistryBrowser_copy_label) {
            public void run() {
                ITreeSelection selection = (ITreeSelection) fFilteredTree.getViewer().getSelection();
                if (selection.isEmpty()) {
                    return;
                }

                String textVersion = ((ILabelProvider) fTreeViewer.getLabelProvider())
                        .getText(selection.getFirstElement());
                if ((textVersion != null) && (textVersion.trim().length() > 0)) {
                    // set the clipboard contents
                    fClipboard.setContents(new Object[] { textVersion },
                            new Transfer[] { TextTransfer.getInstance() });
                }
            }
        };
        fCopyAction.setImageDescriptor(PDERuntimePluginImages.COPY_QNAME);

        fGroupByBundlesAction = new GroupByAction(PDERuntimeMessages.RegistryBrowser_Bundle, BUNDLES);
        int groupBy = getGroupBy();
        fGroupByBundlesAction.setChecked(groupBy == BUNDLES);
        fGroupByExtensionPointsAction = new GroupByAction(PDERuntimeMessages.RegistryBrowser_ExtensionPoint,
                EXTENSION_REGISTRY);
        fGroupByExtensionPointsAction.setChecked(groupBy == EXTENSION_REGISTRY);
        fGroupByServicesAction = new GroupByAction(PDERuntimeMessages.RegistryBrowser_Service, SERVICES);
        fGroupByServicesAction.setChecked(groupBy == SERVICES);

        fShowAdvancedOperationsAction = new Action(PDERuntimeMessages.RegistryView_showAdvanced_label) {
            public void run() { // do nothing
            }
        };
        fShowAdvancedOperationsAction.setChecked(fMemento.getString(SHOW_ADVANCED_MODE).equals("true")); //$NON-NLS-1$

        fStartAction = new Action(PDERuntimeMessages.RegistryView_startAction_label) {
            public void run() {
                try {
                    List bundles = getSelectedBundles();
                    for (Iterator it = bundles.iterator(); it.hasNext();) {
                        Bundle bundle = (Bundle) it.next();
                        bundle.start();
                    }
                } catch (BundleException e) {
                    PDERuntimePlugin.log(e);
                }
            }
        };

        fStopAction = new Action(PDERuntimeMessages.RegistryView_stopAction_label) {
            public void run() {
                try {
                    List bundles = getSelectedBundles();
                    for (Iterator it = bundles.iterator(); it.hasNext();) {
                        Bundle bundle = (Bundle) it.next();
                        bundle.stop();
                    }
                } catch (BundleException e) {
                    PDERuntimePlugin.log(e);
                }
            }
        };

        fEnableAction = new Action(PDERuntimeMessages.RegistryView_enableAction_label) {
            public void run() {
                List bundles = getSelectedBundles();
                for (Iterator it = bundles.iterator(); it.hasNext();) {
                    Bundle bundle = (Bundle) it.next();
                    bundle.enable();
                }
            }
        };

        fDisableAction = new Action(PDERuntimeMessages.RegistryView_disableAction_label) {
            public void run() {
                List bundles = getSelectedBundles();
                for (Iterator it = bundles.iterator(); it.hasNext();) {
                    Bundle bundle = (Bundle) it.next();
                    bundle.disable();
                }
            }
        };

        fDiagnoseAction = new Action(PDERuntimeMessages.RegistryView_diagnoseAction_label) {
            public void run() {
                List bundles = getSelectedBundles();
                for (Iterator it = bundles.iterator(); it.hasNext();) {
                    Bundle bundle = (Bundle) it.next();
                    MultiStatus problems = bundle.diagnose();

                    Dialog dialog;
                    if ((problems != null) && (problems.getChildren().length > 0)) {
                        dialog = new DiagnosticsDialog(getSite().getShell(),
                                PDERuntimeMessages.RegistryView_diag_dialog_title, null, problems, IStatus.WARNING);
                        dialog.open();
                    } else {
                        MessageDialog.openInformation(getSite().getShell(),
                                PDERuntimeMessages.RegistryView_diag_dialog_title,
                                PDERuntimeMessages.RegistryView_no_unresolved_constraints);
                    }

                }
            }
        };

        fCollapseAllAction = new Action("collapseAll") { //$NON-NLS-1$
            public void run() {
                fTreeViewer.collapseAll();
            }
        };
        fCollapseAllAction.setText(PDERuntimeMessages.RegistryView_collapseAll_label);
        fCollapseAllAction.setImageDescriptor(PDERuntimePluginImages.DESC_COLLAPSE_ALL);
        fCollapseAllAction.setToolTipText(PDERuntimeMessages.RegistryView_collapseAll_tooltip);
    }

    public int getGroupBy() {
        return fMemento.getInteger(GROUP_BY).intValue();
    }

    public void updateTitle() {
        setContentDescription(getTitleSummary());
    }

    protected Tree getUndisposedTree() {
        if (fTreeViewer == null || fTreeViewer.getTree() == null || fTreeViewer.getTree().isDisposed())
            return null;
        return fTreeViewer.getTree();
    }

    public String getTitleSummary() {
        Tree tree = getUndisposedTree();
        String type;
        int total = 0;
        switch (getGroupBy()) {
        default:
        case BUNDLES:
            type = PDERuntimeMessages.RegistryBrowser_plugins;
            total = model.getBundles().length;
            break;
        case EXTENSION_REGISTRY:
            type = PDERuntimeMessages.RegistryBrowser_extensionPoints;
            total = model.getExtensionPoints().length;
            break;
        case SERVICES:
            type = PDERuntimeMessages.RegistryBrowser_Services;
            total = model.getServiceNames().length;
            break;
        }

        if (tree == null)
            return NLS.bind(PDERuntimeMessages.RegistryView_titleSummary, (new String[] { "0", "0", type })); //$NON-NLS-1$ //$NON-NLS-2$
        return NLS.bind(PDERuntimeMessages.RegistryView_titleSummary,
                (new String[] { Integer.toString(tree.getItemCount()), Integer.toString(total), type }));
    }

    private boolean isBundleSelected() {
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        if (selection != null) {
            Object[] elements = selection.toArray();
            for (int i = 0; i < elements.length; i++) {
                if (!(elements[i] instanceof Bundle)) {
                    return false;
                }
            }
        }

        return true;
    }

    private List getSelectedBundles() {
        List bundles = new ArrayList();
        IStructuredSelection selection = (IStructuredSelection) fTreeViewer.getSelection();
        if (selection != null) {
            Object[] elements = selection.toArray();
            for (int i = 0; i < elements.length; i++) {
                if (elements[i] instanceof Bundle) {
                    bundles.add(elements[i]);
                }
            }
        }
        return bundles;
    }

    /**
     * @return true if none is stopped, false if at least one is stopped
     */
    private boolean selectedBundlesStarted() {
        List bundles = getSelectedBundles();
        for (Iterator it = bundles.iterator(); it.hasNext();) {
            Bundle bundle = (Bundle) it.next();
            if (bundle.getState() != Bundle.ACTIVE)
                return false;
        }
        return true;
    }

    /**
     * @return true if none is active, false if at least one is active
     */
    private boolean selectedBundlesStopped() {
        List bundles = getSelectedBundles();
        for (Iterator it = bundles.iterator(); it.hasNext();) {
            Bundle bundle = (Bundle) it.next();
            if (bundle.getState() == Bundle.ACTIVE)
                return false;
        }
        return true;
    }

    /**
     * @return true if none is enabled, false if at least one is enabled
     */
    private boolean selectedBundlesDisabled() {
        List bundles = getSelectedBundles();
        for (Iterator it = bundles.iterator(); it.hasNext();) {
            Bundle bundle = (Bundle) it.next();
            if (bundle.isEnabled())
                return false;
        }
        return true;
    }

    /**
     * @return true if none is disabled, false if at least one is disabled
     */
    private boolean selectedBundlesEnabled() {
        List bundles = getSelectedBundles();
        for (Iterator it = bundles.iterator(); it.hasNext();) {
            Bundle bundle = (Bundle) it.next();
            if (!bundle.isEnabled())
                return false;
        }
        return true;
    }

    public void add(Object object) {
        Object parent = fContentProvider.getParent(object);
        if (parent == null) {
            add(fTreeViewer.getInput(), object);
        } else {
            refresh(parent);
        }
    }

    protected void add(Object parent, Object object) {
        if (fTreeViewer.getTree().isDisposed())
            return;

        if (fDrillDownAdapter.canGoHome())
            return;
        fTreeViewer.add(parent, object);
        updateTitle();
    }

    public void remove(Object object) {
        if (fTreeViewer.getTree().isDisposed())
            return;

        if (fDrillDownAdapter.canGoHome())
            return;
        fTreeViewer.remove(object);
        updateTitle();
    }

    private boolean filtersEnabled() {
        return fTreeViewer.getFilters().length > 0;
    }

    private void deferredRefresh() {
        if (refreshThread != null)
            return;

        long now = System.currentTimeMillis();
        if (now - lastRefresh > REFRESH_DELAY) {
            fTreeViewer.refresh();
            updateTitle();
            lastRefresh = now;
        } else {
            Runnable runnable = new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(REFRESH_DELAY);
                    } catch (InterruptedException e) {
                        return;
                    }
                    refreshThread = null;
                    if (fTreeViewer.getTree().isDisposed())
                        return;

                    fTreeViewer.getTree().getDisplay().asyncExec(new Runnable() {
                        public void run() {
                            if (!fTreeViewer.getTree().isDisposed()) {
                                fTreeViewer.refresh();
                                updateTitle();
                            }
                        }
                    });
                }
            };
            refreshThread = new Thread(runnable);
            refreshThread.start();
        }
    }

    void refresh(Object[] objects) {
        if (fTreeViewer.getTree().isDisposed())
            return;

        if (filtersEnabled()) {
            deferredRefresh();
        } else {
            for (int i = 0; i < objects.length; i++) {
                fTreeViewer.refresh(objects[i]);
            }
        }
        updateTitle();
    }

    void refresh(Object object) {
        if (fTreeViewer.getTree().isDisposed())
            return;

        if (filtersEnabled()) {
            deferredRefresh();
        } else {
            fTreeViewer.refresh(object);
            updateTitle();
        }
    }

    public Object getAdapter(Class clazz) {
        if (ILabelProvider.class.equals(clazz)) {
            return fLabelProvider;
        }

        if (IContentProvider.class.equals(clazz)) {
            return fContentProvider;
        }

        return super.getAdapter(clazz);
    }
}