/*******************************************************************************
 * Copyright (c) 2003, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.ide;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IBundleGroup;
import org.eclipse.core.runtime.IBundleGroupProvider;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.PluginVersionIdentifier;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
import org.eclipse.ui.internal.WorkbenchImages;
import org.eclipse.ui.internal.dialogs.SelectPerspectiveDialog;
import org.eclipse.ui.internal.ide.dialogs.WelcomeEditorInput;
import org.eclipse.ui.internal.ide.model.WorkbenchAdapterBuilder;
import org.eclipse.ui.internal.progress.ProgressMonitorJobsDialog;
import org.eclipse.ui.part.EditorInputTransfer;
import org.eclipse.ui.part.MarkerTransfer;
import org.eclipse.ui.part.ResourceTransfer;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.update.configurator.ConfiguratorUtils;
import org.eclipse.update.configurator.IPlatformConfiguration;
import org.eclipse.update.core.SiteManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;

/**
 * IDE-specified workbench advisor which configures the workbench for use as
 * an IDE.
 * <p>
 * Note: This class replaces <code>org.eclipse.ui.internal.Workbench</code>.
 * </p>
 * 
 * @since 3.0
 */
public class IDEWorkbenchAdvisor extends WorkbenchAdvisor {
    private static final String ACTION_BUILDER = "ActionBuilder"; //$NON-NLS-1$

    private static final String WELCOME_EDITOR_ID = "org.eclipse.ui.internal.ide.dialogs.WelcomeEditor"; //$NON-NLS-1$

    private static final String WORKBENCH_PREFERENCE_CATEGORY_ID = "org.eclipse.ui.preferencePages.Workbench"; //$NON-NLS-1$

    /**
     * The dialog setting key to access the known installed features
     * since the last time the workbench was run.
     */
    private static final String INSTALLED_FEATURES = "installedFeatures"; //$NON-NLS-1$

    private static IDEWorkbenchAdvisor workbenchAdvisor = null;

    /**
     * Event loop exception handler for the advisor.
     */
    private IDEExceptionHandler exceptionHandler = null;

    /**
     * Contains the workspace location if the -showlocation command line
     * argument is specified, or <code>null</code> if not specified.
     */
    private String workspaceLocation = null;

    /**
     * Ordered map of versioned feature ids -> info that are new for this
     * session; <code>null</code> if uninitialized. Key type:
     * <code>String</code>, Value type: <code>AboutInfo</code>.
     */
    private Map newlyAddedBundleGroups;

    /**
     * List of <code>AboutInfo</code> for all new installed
     * features that specify a welcome perspective.
     */
    private ArrayList welcomePerspectiveInfos = null;

    /**
     * Helper for managing activites in response to workspace changes.
     */
    private IDEWorkbenchActivityHelper activityHelper = null;

    /**
     * Signals that the welcome editors and/or intros have been opened.
     */
    private boolean editorsAndIntrosOpened = false;

    /**
     * Creates a new workbench advisor instance.
     */
    protected IDEWorkbenchAdvisor() {
        super();
        if (workbenchAdvisor != null) {
            throw new IllegalStateException();
        }
        workbenchAdvisor = this;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#initialize
     */
    public void initialize(IWorkbenchConfigurer configurer) {

        // make sure we always save and restore workspace state
        configurer.setSaveAndRestore(true);

        // setup the event loop exception handler
        exceptionHandler = new IDEExceptionHandler(configurer);

        // register workspace adapters
        WorkbenchAdapterBuilder.registerAdapters();

        // get the command line arguments
        String[] cmdLineArgs = Platform.getCommandLineArgs();

        // include the workspace location in the title 
        // if the command line option -showlocation is specified
        for (int i = 0; i < cmdLineArgs.length; i++) {
            if ("-showlocation".equalsIgnoreCase(cmdLineArgs[i])) { //$NON-NLS-1$
                workspaceLocation = Platform.getLocation().toOSString();
                break;
            }
        }

        // register shared images
        declareWorkbenchImages();

        // initialize the activity helper
        activityHelper = IDEWorkbenchActivityHelper.getInstance();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#preStartup()
     */
    public void preStartup() {

        //Suspend background jobs while we startup
        Platform.getJobManager().suspend();

        // support old welcome perspectives if intro plugin is not present
        if (!hasIntro()) {
            Map m = getNewlyAddedBundleGroups();
            welcomePerspectiveInfos = new ArrayList(m.size());
            for (Iterator i = m.values().iterator(); i.hasNext();) {
                AboutInfo info = (AboutInfo) i.next();
                if (info != null && info.getWelcomePerspectiveId() != null
                        && info.getWelcomePageURL() != null)
                    welcomePerspectiveInfos.add(info);
            }
        }

        //Register the build actions
        IProgressService service = PlatformUI.getWorkbench()
                .getProgressService();
        ImageDescriptor newImage = IDEInternalWorkbenchImages
                .getImageDescriptor(IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC);
        service.registerIconForFamily(newImage,
                ResourcesPlugin.FAMILY_MANUAL_BUILD);
        service.registerIconForFamily(newImage,
                ResourcesPlugin.FAMILY_AUTO_BUILD);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#postStartup()
     */
    public void postStartup() {
        try {
            refreshFromLocal();
            checkUpdates();
        } finally {//Resume background jobs after we startup
            Platform.getJobManager().resume();
        }

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#postShutdown
     */
    public void postShutdown() {
        if (activityHelper != null) {
            activityHelper.shutdown();
            activityHelper = null;
        }
        if (IDEWorkbenchPlugin.getPluginWorkspace() != null) {
            disconnectFromWorkspace();
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#eventLoopException
     */
    public void eventLoopException(Throwable exception) {
        super.eventLoopException(exception);
        if (exceptionHandler != null) {
            exceptionHandler.handleException(exception);
        } else {
            if (getWorkbenchConfigurer() != null) {
                getWorkbenchConfigurer().emergencyClose();
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.ui.application.WorkbenchAdvisor#preWindowShellClose
     */
    public boolean preWindowShellClose(
            IWorkbenchWindowConfigurer windowConfigurer) {
        if (getWorkbenchConfigurer().getWorkbench().getWorkbenchWindowCount() > 1) {
            return true;
        }
        // the user has asked to close the last window, while will cause the
        // workbench to close in due course - prompt the user for confirmation
        IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
                .getPreferenceStore();
        boolean promptOnExit = store
                .getBoolean(IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW);

        if (promptOnExit) {
            String message;

            String productName = null;
            IProduct product = Platform.getProduct();
            if (product != null) {
                productName = product.getName();
            }
            if (productName == null) {
                message = IDEWorkbenchMessages
                        .getString("PromptOnExitDialog.message0"); //$NON-NLS-1$
            } else {
                message = IDEWorkbenchMessages
                        .format(
                                "PromptOnExitDialog.message1", new Object[] { productName }); //$NON-NLS-1$
            }

            MessageDialogWithToggle dlg = MessageDialogWithToggle
                    .openOkCancelConfirm(windowConfigurer.getWindow()
                            .getShell(), IDEWorkbenchMessages
                            .getString("PromptOnExitDialog.shellTitle"), //$NON-NLS-1$,
                            message, IDEWorkbenchMessages
                                    .getString("PromptOnExitDialog.choice"), //$NON-NLS-1$,
                            false, null, null);
            if (dlg.getReturnCode() != IDialogConstants.OK_ID) {
                return false;
            }
            if (dlg.getToggleState()) {
                store
                        .setValue(
                                IDEInternalPreferences.EXIT_PROMPT_ON_CLOSE_LAST_WINDOW,
                                false);
                IDEWorkbenchPlugin.getDefault().savePluginPreferences();
            }
        }

        return true;
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#preWindowOpen
     */
    public void preWindowOpen(IWorkbenchWindowConfigurer windowConfigurer) {

        // show the shortcut bar and progress indicator, which are hidden by default
        windowConfigurer.setShowPerspectiveBar(true);
        windowConfigurer.setShowFastViewBars(true);
        windowConfigurer.setShowProgressIndicator(true);

        // add the drag and drop support for the editor area
        windowConfigurer.addEditorAreaTransfer(EditorInputTransfer
                .getInstance());
        windowConfigurer.addEditorAreaTransfer(ResourceTransfer.getInstance());
        windowConfigurer.addEditorAreaTransfer(MarkerTransfer.getInstance());
        windowConfigurer
                .configureEditorAreaDropListener(new EditorAreaDropAdapter(
                        windowConfigurer.getWindow()));

        // hook up the listeners to update the window title
        windowConfigurer.getWindow().addPageListener(new IPageListener() {
            public void pageActivated(IWorkbenchPage page) {
                // do nothing
            }

            public void pageClosed(IWorkbenchPage page) {
                updateTitle(page.getWorkbenchWindow());
            }

            public void pageOpened(IWorkbenchPage page) {
                // do nothing
            }
        });
        windowConfigurer.getWindow().addPerspectiveListener(
                new IPerspectiveListener() {
                    public void perspectiveActivated(IWorkbenchPage page,
                            IPerspectiveDescriptor perspective) {
                        updateTitle(page.getWorkbenchWindow());
                    }

                    public void perspectiveChanged(IWorkbenchPage page,
                            IPerspectiveDescriptor perspective, String changeId) {
                        // do nothing
                    }
                });
        windowConfigurer.getWindow().getPartService().addPartListener(
                new IPartListener2() {
                    public void partActivated(IWorkbenchPartReference ref) {
                        if (ref instanceof IEditorReference
                                || ref.getPage().getActiveEditor() == null) {
                            updateTitle(ref.getPage().getWorkbenchWindow());
                        }
                    }

                    public void partBroughtToTop(IWorkbenchPartReference ref) {
                        if (ref instanceof IEditorReference
                                || ref.getPage().getActiveEditor() == null) {
                            updateTitle(ref.getPage().getWorkbenchWindow());
                        }
                    }

                    public void partClosed(IWorkbenchPartReference ref) {
                        // do nothing
                    }

                    public void partDeactivated(IWorkbenchPartReference ref) {
                        // do nothing
                    }

                    public void partOpened(IWorkbenchPartReference ref) {
                        // do nothing
                    }

                    public void partHidden(IWorkbenchPartReference ref) {
                        // do nothing
                    }

                    public void partVisible(IWorkbenchPartReference ref) {
                        // do nothing
                    }

                    public void partInputChanged(IWorkbenchPartReference ref) {
                        // do nothing
                    }
                });
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#postWindowRestore
     */
    public void postWindowRestore(IWorkbenchWindowConfigurer windowConfigurer)
            throws WorkbenchException {
        int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;

        if (index >= 0 && welcomePerspectiveInfos != null
                && index < welcomePerspectiveInfos.size()) {
            // find a page that exist in the window
            IWorkbenchPage page = windowConfigurer.getWindow().getActivePage();
            if (page == null) {
                IWorkbenchPage pages[] = windowConfigurer.getWindow()
                        .getPages();
                if (pages != null && pages.length > 0)
                    page = pages[0];
            }

            // if the window does not contain a page, create one
            String perspectiveId = ((AboutInfo) welcomePerspectiveInfos
                    .get(index)).getWelcomePerspectiveId();
            if (page == null) {
                IAdaptable root = getDefaultPageInput();
                page = windowConfigurer.getWindow().openPage(perspectiveId,
                        root);
            } else {
                IPerspectiveRegistry reg = PlatformUI.getWorkbench()
                        .getPerspectiveRegistry();
                IPerspectiveDescriptor desc = reg
                        .findPerspectiveWithId(perspectiveId);
                if (desc != null) {
                    page.setPerspective(desc);
                }
            }

            // set the active page and open the welcome editor
            windowConfigurer.getWindow().setActivePage(page);
            page.openEditor(new WelcomeEditorInput(
                    (AboutInfo) welcomePerspectiveInfos.get(index)),
                    WELCOME_EDITOR_ID, true);
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#postWindowClose
     */
    public void postWindowClose(IWorkbenchWindowConfigurer windowConfigurer) {
        WorkbenchActionBuilder a = (WorkbenchActionBuilder) windowConfigurer
                .getData(ACTION_BUILDER);
        if (a != null) {
            windowConfigurer.setData(ACTION_BUILDER, null);
            a.dispose();
        }
    }

    private void refreshFromLocal() {
        String[] commandLineArgs = Platform.getCommandLineArgs();
        IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
                .getPreferenceStore();
        boolean refresh = store
                .getBoolean(IDEInternalPreferences.REFRESH_WORKSPACE_ON_STARTUP);
        if (!refresh)
            return;

        //Do not refresh if it was already done by core on startup.
        for (int i = 0; i < commandLineArgs.length; i++)
            if (commandLineArgs[i].equalsIgnoreCase("-refresh")) //$NON-NLS-1$
                return;

        IWorkbenchWindow window = getWorkbenchConfigurer().getWorkbench()
                .getActiveWorkbenchWindow();
        Shell shell = window == null ? null : window.getShell();
        ProgressMonitorDialog dlg = new ProgressMonitorJobsDialog(shell);
        final CoreException ex[] = new CoreException[1];
        try {
            dlg.run(true, true, new IRunnableWithProgress() {
                public void run(IProgressMonitor monitor)
                        throws InvocationTargetException, InterruptedException {
                    try {
                        IContainer root = ResourcesPlugin.getWorkspace()
                                .getRoot();
                        root.refreshLocal(IResource.DEPTH_INFINITE, monitor);
                    } catch (CoreException e) {
                        ex[0] = e;
                    }
                }
            });
            if (ex[0] != null) {
                ErrorDialog.openError(shell, IDEWorkbenchMessages
                        .getString("Workspace.problemsTitle"), //$NON-NLS-1$ 
                        IDEWorkbenchMessages
                                .getString("Workspace.problemMessage"), //$NON-NLS-1$
                        ex[0].getStatus());
            }
        } catch (InterruptedException e) {
            //Do nothing. Operation was canceled.
        } catch (InvocationTargetException e) {
            String msg = "InvocationTargetException refreshing from local on startup"; //$NON-NLS-1$
            IDEWorkbenchPlugin.log(msg, new Status(IStatus.ERROR,
                    IDEWorkbenchPlugin.IDE_WORKBENCH, 0, msg, e
                            .getTargetException()));
        }
    }

    /**
     * Disconnect from the core workspace.
     */
    private void disconnectFromWorkspace() {
        // save the workspace
        final MultiStatus status = new MultiStatus(
                IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages
                        .getString("ProblemSavingWorkbench"), null); //$NON-NLS-1$
        IRunnableWithProgress runnable = new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) {
                try {
                    status.merge(ResourcesPlugin.getWorkspace().save(true,
                            monitor));
                } catch (CoreException e) {
                    status.merge(e.getStatus());
                }
            }
        };
        try {
            new ProgressMonitorJobsDialog(null).run(true, false, runnable);
        } catch (InvocationTargetException e) {
            status
                    .merge(new Status(
                            IStatus.ERROR,
                            IDEWorkbenchPlugin.IDE_WORKBENCH,
                            1,
                            IDEWorkbenchMessages.getString("InternalError"), e.getTargetException())); //$NON-NLS-1$
        } catch (InterruptedException e) {
            status.merge(new Status(IStatus.ERROR,
                    IDEWorkbenchPlugin.IDE_WORKBENCH, 1, IDEWorkbenchMessages
                            .getString("InternalError"), e)); //$NON-NLS-1$
        }
        ErrorDialog.openError(null, IDEWorkbenchMessages
                .getString("ProblemsSavingWorkspace"), //$NON-NLS-1$
                null, status, IStatus.ERROR | IStatus.WARNING);
        if (!status.isOK()) {
            IDEWorkbenchPlugin.log(IDEWorkbenchMessages
                    .getString("ProblemsSavingWorkspace"), status); //$NON-NLS-1$
        }
    }

    /**
     * Checks if the -newUpdates command line argument is present
     * and if so, opens the update manager.
     */
    private void checkUpdates() {
        boolean newUpdates = false;
        String[] commandLineArgs = Platform.getCommandLineArgs();
        for (int i = 0; i < commandLineArgs.length; i++) {
            if (commandLineArgs[i].equalsIgnoreCase("-newUpdates")) { //$NON-NLS-1$
                newUpdates = true;
                break;
            }
        }

        if (newUpdates) {
            try {
                SiteManager.handleNewChanges();
            } catch (CoreException e) {
                IDEWorkbenchPlugin.log(
                        "Problem opening update manager", e.getStatus()); //$NON-NLS-1$
            }
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#isApplicationMenu
     */
    public boolean isApplicationMenu(
            IWorkbenchWindowConfigurer windowConfigurer, String menuID) {
        WorkbenchActionBuilder a = (WorkbenchActionBuilder) windowConfigurer
                .getData(ACTION_BUILDER);
        return a.isContainerMenu(menuID);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#getDefaultPageInput
     */
    public IAdaptable getDefaultPageInput() {
        return ResourcesPlugin.getWorkspace().getRoot();
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor
     */
    public String getInitialWindowPerspectiveId() {
        int index = PlatformUI.getWorkbench().getWorkbenchWindowCount() - 1;

        String perspectiveId = null;
        if (index >= 0 && welcomePerspectiveInfos != null
                && index < welcomePerspectiveInfos.size()) {
            perspectiveId = ((AboutInfo) welcomePerspectiveInfos.get(index))
                    .getWelcomePerspectiveId();
        }
        if (perspectiveId == null) {
            perspectiveId = IDE.RESOURCE_PERSPECTIVE_ID;
        }
        return perspectiveId;
    }

    /*
     * Open the welcome editor for the primary feature and
     * for any newly installed features.
     */
    private void openWelcomeEditors(IWorkbenchWindow window) {
        if (IDEWorkbenchPlugin.getDefault().getPreferenceStore().getBoolean(
                IDEInternalPreferences.WELCOME_DIALOG)) {
            // show the welcome page for the product the first time the workbench opens
            IProduct product = Platform.getProduct();
            if (product == null)
                return;

            AboutInfo productInfo = new AboutInfo(product);
            URL url = productInfo.getWelcomePageURL();
            if (url == null)
                return;

            IDEWorkbenchPlugin.getDefault().getPreferenceStore().setValue(
                    IDEInternalPreferences.WELCOME_DIALOG, false);
            openWelcomeEditor(window, new WelcomeEditorInput(productInfo), null);
        } else {
            // Show the welcome page for any newly installed features
            List welcomeFeatures = new ArrayList();
            for (Iterator it = getNewlyAddedBundleGroups().entrySet()
                    .iterator(); it.hasNext();) {
                Map.Entry entry = (Map.Entry) it.next();
                String versionedId = (String) entry.getKey();
                String featureId = versionedId.substring(0, versionedId
                        .indexOf(':'));
                AboutInfo info = (AboutInfo) entry.getValue();

                if (info != null && info.getWelcomePageURL() != null) {
                    welcomeFeatures.add(info);
                    // activate the feature plug-in so it can run some install code
                    IPlatformConfiguration platformConfiguration = ConfiguratorUtils
                            .getCurrentPlatformConfiguration();
                    IPlatformConfiguration.IFeatureEntry feature = platformConfiguration
                            .findConfiguredFeatureEntry(featureId);
                    if (feature != null) {
                        String pi = feature.getFeaturePluginIdentifier();
                        if (pi != null) {
                        	//Start the bundle if there is one
                        	Bundle bundle = Platform.getBundle(pi);
                        	if(bundle != null)
                        		try{
                        			bundle.start();
                        		}
                            	catch(BundleException exception){
                            		IDEWorkbenchPlugin.log("Failed to load feature", exception);//$NON-NLS-1$
                            	}
                        }
                    }
                }
            }

            int wCount = getWorkbenchConfigurer().getWorkbench()
                    .getWorkbenchWindowCount();
            for (int i = 0; i < welcomeFeatures.size(); i++) {
                AboutInfo newInfo = (AboutInfo) welcomeFeatures.get(i);
                String id = newInfo.getWelcomePerspectiveId();
                // Other editors were already opened in postWindowRestore(..)
                if (id == null || i >= wCount) {
                    openWelcomeEditor(window, new WelcomeEditorInput(newInfo),
                            id);
                }
            }
        }
    }

    /**
     * Returns the map of versioned feature ids -> info object for all installed
     * features. The format of the versioned feature id (the key of the map) is
     * featureId + ":" + versionId.
     * 
     * @return map of versioned feature ids -> info object (key type:
     *         <code>String</code>, value type: <code>AboutInfo</code>)
     * @since 3.0
     */
    private Map computeBundleGroupMap() {
        // use tree map to get predicable order
        Map ids = new TreeMap();

        IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
        for (int i = 0; i < providers.length; ++i) {
            IBundleGroup[] groups = providers[i].getBundleGroups();
            for (int j = 0; j < groups.length; ++j) {
                IBundleGroup group = groups[j];
                AboutInfo info = new AboutInfo(group);

                String version = info.getVersionId();
                version = version == null ? "0.0.0" //$NON-NLS-1$
                        : new PluginVersionIdentifier(version).toString();
                String versionedFeature = group.getIdentifier() + ":" + version; //$NON-NLS-1$

                ids.put(versionedFeature, info);
            }
        }

        return ids;
    }

    /**
     * Returns the ordered map of versioned feature ids -> AboutInfo that are
     * new for this session.
     * 
     * @return ordered map of versioned feature ids (key type:
     *         <code>String</code>) -> infos (value type:
     *         <code>AboutInfo</code>).
     */
    private Map getNewlyAddedBundleGroups() {
        if (newlyAddedBundleGroups == null)
            newlyAddedBundleGroups = createNewBundleGroupsMap();
        return newlyAddedBundleGroups;
    }

    /**
     * Updates the old features setting and returns a map of new features.
     */
    private Map createNewBundleGroupsMap() {
        // retrieve list of installed bundle groups from last session	
        IDialogSettings settings = IDEWorkbenchPlugin.getDefault()
                .getDialogSettings();
        String[] previousFeaturesArray = settings.getArray(INSTALLED_FEATURES);

        // get a map of currently installed bundle groups and store it for next session
        Map bundleGroups = computeBundleGroupMap();
        String[] currentFeaturesArray = new String[bundleGroups.size()];
        bundleGroups.keySet().toArray(currentFeaturesArray);
        settings.put(INSTALLED_FEATURES, currentFeaturesArray);

        // remove the previously known from the current set
        if (previousFeaturesArray != null)
            for (int i = 0; i < previousFeaturesArray.length; ++i)
                bundleGroups.remove(previousFeaturesArray[i]);

        return bundleGroups;
    }

    /*
     * Open a welcome editor for the given input
     */
    private void openWelcomeEditor(IWorkbenchWindow window,
            WelcomeEditorInput input, String perspectiveId) {
        if (getWorkbenchConfigurer().getWorkbench().getWorkbenchWindowCount() == 0) {
            // Something is wrong, there should be at least
            // one workbench window open by now.
            return;
        }

        IWorkbenchWindow win = window;
        if (perspectiveId != null) {
            try {
                win = getWorkbenchConfigurer().getWorkbench()
                        .openWorkbenchWindow(perspectiveId,
                                getDefaultPageInput());
                if (win == null) {
                    win = window;
                }
            } catch (WorkbenchException e) {
                IDEWorkbenchPlugin
                        .log(
                                "Error opening window with welcome perspective.", e.getStatus()); //$NON-NLS-1$
                return;
            }
        }

        if (win == null) {
            win = getWorkbenchConfigurer().getWorkbench().getWorkbenchWindows()[0];
        }

        IWorkbenchPage page = win.getActivePage();
        String id = perspectiveId;
        if (id == null) {
            id = getWorkbenchConfigurer().getWorkbench()
                    .getPerspectiveRegistry().getDefaultPerspective();
        }

        if (page == null) {
            try {
                page = win.openPage(id, getDefaultPageInput());
            } catch (WorkbenchException e) {
                ErrorDialog.openError(win.getShell(), IDEWorkbenchMessages
                        .getString("Problems_Opening_Page"), //$NON-NLS-1$
                        e.getMessage(), e.getStatus());
            }
        }
        if (page == null)
            return;

        if (page.getPerspective() == null) {
            try {
                page = getWorkbenchConfigurer().getWorkbench().showPerspective(
                        id, win);
            } catch (WorkbenchException e) {
                ErrorDialog
                        .openError(
                                win.getShell(),
                                IDEWorkbenchMessages
                                        .getString("Workbench.openEditorErrorDialogTitle"), //$NON-NLS-1$
                                IDEWorkbenchMessages
                                        .getString("Workbench.openEditorErrorDialogMessage"), //$NON-NLS-1$
                                e.getStatus());
                return;
            }
        }

        page.setEditorAreaVisible(true);

        // see if we already have an editor
        IEditorPart editor = page.findEditor(input);
        if (editor != null) {
            page.activate(editor);
            return;
        }

        try {
            page.openEditor(input, WELCOME_EDITOR_ID);
        } catch (PartInitException e) {
            ErrorDialog
                    .openError(
                            win.getShell(),
                            IDEWorkbenchMessages
                                    .getString("Workbench.openEditorErrorDialogTitle"), //$NON-NLS-1$
                            IDEWorkbenchMessages
                                    .getString("Workbench.openEditorErrorDialogMessage"), //$NON-NLS-1$
                            e.getStatus());
        }
        return;
    }

    /**
     * Updates the window title. Format will be:
     * [pageInput -] [currentPerspective -] [editorInput -] [workspaceLocation -] productName
     * @param window The window being updated.
     */
    private void updateTitle(IWorkbenchWindow window) {
        IWorkbenchWindowConfigurer windowConfigurer = getWorkbenchConfigurer()
                .getWindowConfigurer(window);

        String title = null;
        IProduct product = Platform.getProduct();
        if (product != null) {
            title = product.getName();
        }
        if (title == null) {
            title = ""; //$NON-NLS-1$
        }

        if (workspaceLocation != null) {
            title = IDEWorkbenchMessages
                    .format(
                            "WorkbenchWindow.shellTitle", new Object[] { workspaceLocation, title }); //$NON-NLS-1$
        }

        IWorkbenchPage currentPage = window.getActivePage();
        if (currentPage != null) {
            IEditorPart editor = currentPage.getActiveEditor();
            if (editor != null) {
                String editorTitle = editor.getTitle();
                title = IDEWorkbenchMessages
                        .format(
                                "WorkbenchWindow.shellTitle", new Object[] { editorTitle, title }); //$NON-NLS-1$
            }
            IPerspectiveDescriptor persp = currentPage.getPerspective();
            String label = ""; //$NON-NLS-1$
            if (persp != null)
                label = persp.getLabel();
            IAdaptable input = currentPage.getInput();
            if (input != null && !input.equals(getDefaultPageInput())) {
                label = currentPage.getLabel();
            }
            if (label != null && !label.equals("")) { //$NON-NLS-1$	
                title = IDEWorkbenchMessages
                        .format(
                                "WorkbenchWindow.shellTitle", new Object[] { label, title }); //$NON-NLS-1$
            }
        }

        windowConfigurer.setTitle(title);
    }

    /**
     * Declares all IDE-specific workbench images. This includes both "shared"
     * images (named in {@link IDE.SharedImages}) and
     * internal images (named in
     * {@link org.eclipse.ui.internal.ide.IDEInternalWorkbenchImages}).
     * 
     * @see IWorkbenchConfigurer#declareImage
     */
    private void declareWorkbenchImages() {

        final String ICONS_PATH = "icons/full/";//$NON-NLS-1$
        final String PATH_ELOCALTOOL = ICONS_PATH + "elcl16/"; //Enabled toolbar icons.//$NON-NLS-1$
        final String PATH_ETOOL = ICONS_PATH + "etool16/"; //Enabled toolbar icons.//$NON-NLS-1$
        final String PATH_DTOOL = ICONS_PATH + "dtool16/"; //Disabled toolbar icons.//$NON-NLS-1$
        final String PATH_OBJECT = ICONS_PATH + "obj16/"; //Model object icons//$NON-NLS-1$
        final String PATH_WIZBAN = ICONS_PATH + "wizban/"; //Wizard icons//$NON-NLS-1$

        Bundle ideBundle = Platform.getBundle(IDEWorkbenchPlugin.IDE_WORKBENCH);
        declareWorkbenchImage(ideBundle, ISharedImages.IMG_TOOL_NEW_WIZARD,
                PATH_ETOOL + "new_wiz.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                ISharedImages.IMG_TOOL_NEW_WIZARD_HOVER, PATH_ETOOL
                        + "new_wiz.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                ISharedImages.IMG_TOOL_NEW_WIZARD_DISABLED, PATH_DTOOL
                        + "new_wiz.gif", true); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IWorkbenchGraphicConstants.IMG_ETOOL_IMPORT_WIZ, PATH_ETOOL
                        + "import_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IWorkbenchGraphicConstants.IMG_ETOOL_EXPORT_WIZ, PATH_ETOOL
                        + "export_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC, PATH_ETOOL
                        + "build_exec.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_HOVER,
                PATH_ETOOL + "build_exec.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC_DISABLED,
                PATH_DTOOL + "build_exec.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC, PATH_ETOOL
                        + "search_src.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_HOVER,
                PATH_ETOOL + "search_src.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_SEARCH_SRC_DISABLED,
                PATH_DTOOL + "search_src.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_NEXT_NAV, PATH_ETOOL
                        + "next_nav.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_ETOOL_PREVIOUS_NAV, PATH_ETOOL
                        + "prev_nav.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IWorkbenchGraphicConstants.IMG_WIZBAN_NEW_WIZ, PATH_WIZBAN
                        + "new_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWPRJ_WIZ, PATH_WIZBAN
                        + "newprj_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFOLDER_WIZ,
                PATH_WIZBAN + "newfolder_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_NEWFILE_WIZ, PATH_WIZBAN
                        + "newfile_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IWorkbenchGraphicConstants.IMG_WIZBAN_IMPORT_WIZ, PATH_WIZBAN
                        + "import_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTDIR_WIZ,
                PATH_WIZBAN + "importdir_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_IMPORTZIP_WIZ,
                PATH_WIZBAN + "importzip_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IWorkbenchGraphicConstants.IMG_WIZBAN_EXPORT_WIZ, PATH_WIZBAN
                        + "export_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTDIR_WIZ,
                PATH_WIZBAN + "exportdir_wiz.gif", false); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_EXPORTZIP_WIZ,
                PATH_WIZBAN + "exportzip_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_WIZBAN_RESOURCEWORKINGSET_WIZ,
                PATH_WIZBAN + "workset_wiz.gif", false); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJ_PROJECT,
                PATH_OBJECT + "prj_obj.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDE.SharedImages.IMG_OBJ_PROJECT_CLOSED, PATH_OBJECT
                        + "cprj_obj.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OPEN_MARKER,
                PATH_ELOCALTOOL + "gotoobj_tsk.gif", true); //$NON-NLS-1$

        // task objects
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_HPRIO_TSK, PATH_OBJECT+"hprio_tsk.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_MPRIO_TSK, PATH_OBJECT+"mprio_tsk.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LPRIO_TSK, PATH_OBJECT+"lprio_tsk.gif");

        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_TASK_TSK,
                PATH_OBJECT + "taskmrk_tsk.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle, IDE.SharedImages.IMG_OBJS_BKMRK_TSK,
                PATH_OBJECT + "bkmrk_tsk.gif", true); //$NON-NLS-1$

        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_OBJS_COMPLETE_TSK, PATH_OBJECT
                        + "complete_tsk.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_OBJS_INCOMPLETE_TSK, PATH_OBJECT
                        + "incomplete_tsk.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_ITEM, PATH_OBJECT
                        + "welcome_item.gif", true); //$NON-NLS-1$
        declareWorkbenchImage(ideBundle,
                IDEInternalWorkbenchImages.IMG_OBJS_WELCOME_BANNER, PATH_OBJECT
                        + "welcome_banner.gif", true); //$NON-NLS-1$

        // synchronization indicator objects
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_WBET_STAT, PATH_OVERLAY+"wbet_stat.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_SBET_STAT, PATH_OVERLAY+"sbet_stat.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_CONFLICT_STAT, PATH_OVERLAY+"conflict_stat.gif");

        // content locality indicator objects
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_NOTLOCAL_STAT, PATH_STAT+"notlocal_stat.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_LOCAL_STAT, PATH_STAT+"local_stat.gif");
        //declareRegistryImage(IDEInternalWorkbenchImages.IMG_OBJS_FILLLOCAL_STAT, PATH_STAT+"filllocal_stat.gif");
    }

    /**
     * Declares an IDE-specific workbench image.
     * 
     * @param symbolicName the symbolic name of the image
     * @param path the path of the image file; this path is relative to the base
     * of the IDE plug-in
     * @param shared <code>true</code> if this is a shared image, and
     * <code>false</code> if this is not a shared image
     * @see IWorkbenchConfigurer#declareImage
     */
    private void declareWorkbenchImage(Bundle ideBundle, String symbolicName,
            String path, boolean shared) {
        URL url = ideBundle.getEntry(path);
        ImageDescriptor desc = ImageDescriptor.createFromURL(url);
        getWorkbenchConfigurer().declareImage(symbolicName, desc, shared);
    }

    public void fillActionBars(IWorkbenchWindow window,
            IActionBarConfigurer actionConfigurer, int flags) {

        // setup the action builder to populate the toolbar and menubar in the configurer
        WorkbenchActionBuilder actionBuilder = null;
        IWorkbenchWindowConfigurer windowConfigurer = getWorkbenchConfigurer()
                .getWindowConfigurer(window);

        // For proxy calls to this method it is important that we use the same object
        // associated with the windowConfigurer
        actionBuilder = (WorkbenchActionBuilder) windowConfigurer
                .getData(ACTION_BUILDER);
        if (actionBuilder == null) {
            actionBuilder = new WorkbenchActionBuilder(window);
        }

        if ((flags & FILL_PROXY) != 0) {
            // Filling in fake actionbars
            if ((flags & FILL_MENU_BAR) != 0) {
                actionBuilder.populateMenuBar(actionConfigurer);
            }
            if ((flags & FILL_COOL_BAR) != 0) {
                actionBuilder.populateCoolBar(actionConfigurer);
            }
        } else {
            // make, fill, and hook listeners to action builder
            // reference to IWorkbenchConfigurer is need for the ABOUT action
            windowConfigurer.setData(ACTION_BUILDER, actionBuilder);
            actionBuilder.makeAndPopulateActions(getWorkbenchConfigurer(),
                    actionConfigurer);
        }

    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.application.WorkbenchAdvisor#getMainPreferencePageId
     */
    public String getMainPreferencePageId() {
        // indicate that we want the Workench preference page to be prominent
        return WORKBENCH_PREFERENCE_CATEGORY_ID;
    }

    /**
     * Tries to open the intro,if one exists and otherwise will open the legacy 
     * Welcome pages.
     * 
     * @see org.eclipse.ui.application.WorkbenchAdvisor#openIntro(org.eclipse.ui.application.IWorkbenchWindowConfigurer)
     */
    public void openIntro(IWorkbenchWindowConfigurer windowConfigurer) {
        if (editorsAndIntrosOpened)
            return;

        editorsAndIntrosOpened = true;

        // don't try to open the welcome editors if there is an intro
        if (hasIntro())
            super.openIntro(windowConfigurer);
        else {
            openWelcomeEditors(windowConfigurer.getWindow());
            // save any preferences changes caused by the above actions
            IDEWorkbenchPlugin.getDefault().savePluginPreferences();
        }
    }

    /**
     * Return true if the intro plugin is present and false otherwise.
     */
    private boolean hasIntro() {
        IWorkbenchConfigurer wc = getWorkbenchConfigurer();
        return wc == null ? false : wc.getWorkbench().getIntroManager()
                .hasIntro();
    }

    /**
     * Returns the workbench action builder for the given window 
     * @param window
     * @return WorkbenchActionBuilder
     */
    static WorkbenchActionBuilder getActionBuilder(IWorkbenchWindow window) {
        IWorkbenchWindowConfigurer configurer = workbenchAdvisor
                .getWorkbenchConfigurer().getWindowConfigurer(window);
        return (WorkbenchActionBuilder) configurer.getData("ActionBuilder"); //$NON-NLS-1$
    }
    
    /* (non-Javadoc)
	 * @see org.eclipse.ui.application.WorkbenchAdvisor#createEmptyWindowContents(org.eclipse.ui.application.IWorkbenchWindowConfigurer, org.eclipse.swt.widgets.Composite)
	 */
	public Control createEmptyWindowContents(final IWorkbenchWindowConfigurer configurer, Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setLayout(new GridLayout(2, false));
		Display display = composite.getDisplay();
		Color bgCol = display.getSystemColor(SWT.COLOR_DARK_GRAY);
		composite.setBackground(bgCol);
        Label label = new Label(composite, SWT.WRAP);
        label.setForeground(display.getSystemColor(SWT.COLOR_WHITE));
        label.setBackground(bgCol);
        label.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
        String msg = IDEWorkbenchMessages.getString("IDEWorkbenchAdvisor.noPerspective"); //$NON-NLS-1$
        label.setText(msg);
        ToolBarManager toolBarManager = new ToolBarManager();
        // TODO: should obtain the open perspective action from ActionFactory
        IAction openPerspectiveAction = new Action() {
        	{ setToolTipText(IDEWorkbenchMessages.getString("IDEWorkbenchAdvisor.openPerspective")); //$NON-NLS-1$
        	  setImageDescriptor(WorkbenchImages.getImageDescriptor(
                    IWorkbenchGraphicConstants.IMG_ETOOL_NEW_PAGE));
        	}
        	public void run() {
                SelectPerspectiveDialog dlg = new SelectPerspectiveDialog(configurer.getWindow().getShell(),
                        configurer.getWindow().getWorkbench().getPerspectiveRegistry());
                dlg.open();
                if (dlg.getReturnCode() == Window.CANCEL)
                    return;
                IPerspectiveDescriptor desc = dlg.getSelection();
                if (desc != null) {
                    try {
						configurer.getWindow().openPage(desc.getId(), getDefaultPageInput());
					} catch (WorkbenchException e) {
						IDEWorkbenchPlugin.log("Error opening page", e); //$NON-NLS-1$
					}
                }
        	}
        };
        toolBarManager.add(openPerspectiveAction);
        ToolBar toolBar = toolBarManager.createControl(composite);
        toolBar.setBackground(bgCol);
        return composite;
	}
}