/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 * Martin Oberhuber (Wind River) - [325557] Perspective "none" is not persisted
 *******************************************************************************/
package org.eclipse.debug.internal.ui.launchConfigurations;


import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.eclipse.core.commands.contexts.Context;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
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.Job;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationType;
import org.eclipse.debug.core.ILaunchDelegate;
import org.eclipse.debug.core.ILaunchListener;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.internal.core.IConfigurationElementConstants;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.core.LaunchManager;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.viewers.AsynchronousSchedulingRuleFactory;
import org.eclipse.debug.internal.ui.views.ViewContextManager;
import org.eclipse.debug.internal.ui.views.ViewContextService;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.contexts.ISuspendTrigger;
import org.eclipse.debug.ui.contexts.ISuspendTriggerListener;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.contexts.IContextActivation;
import org.eclipse.ui.contexts.IContextService;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.ibm.icu.text.MessageFormat;

/**
 * The perspective manager manages the 'perspective' settings
 * defined by launch configurations. Specifically it:
 * <ul>
 * <li>changes perspectives as launches are registered</li>
 * <li>change perspective when a thread suspends</li>
 * </ul>
 *
 * Since 3.3 the Perspectives Manager is an <code>ISaveParticipant</code>, allowing it to participate in
 * workspace persistence life-cycles.
 *
 * @see IDebugUIContants.ATTR_RUN_PERSPECTIVE
 * @see IDebugUIContants.ATTR_DEBUG_PERSPECTIVE
 * @see ISaveParticipant
 * @see ISuspendTriggerListener
 * @see ILaunchListener
 * @see org.eclipse.debug.internal.ui.preferences.LaunchPerspectivePreferencePage
 * @see DebugUIPlugin
 */
public class PerspectiveManager implements ILaunchListener, ISuspendTriggerListener, ISaveParticipant {

	/**
	 * Describes exactly one perspective context, which is composed of an <code>ILaunchCOnfigurationType</code>, and set of modes
	 * and an <code>ILaunchDelegate</code>. Perspective ids are then cached for a context based on mode set.
	 *
	 * @since 3.3
	 */
	class PerspectiveContext {

		private ILaunchConfigurationType fType = null;
		private ILaunchDelegate fDelegate = null;
		private Map<Set<String>, String> fPerspectives = null;

		/**
		 * Constructor
		 * @param type
		 * @param delegate
		 * @param modes
		 */
		public PerspectiveContext(ILaunchConfigurationType type, ILaunchDelegate delegate, Set<String> modes) {
			fType = type;
			fDelegate = delegate;
			fPerspectives = new HashMap<>();
			fPerspectives.put(modes, null);
		}

		/**
		 * We can specially compare two cases:
		 * <ol>
		 * <li>a launch object</li>
		 * <li>an object array of the form [IlaunchConfigurationType, ILaunchDelegate, Set]</li>
		 * </ol>
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		@Override
		public boolean equals(Object object) {
			ILaunchDelegate delegate = null;
			ILaunchConfigurationType type = null;
			if(object instanceof ILaunch) {
				try {
					ILaunch launch = (ILaunch) object;
					type = launch.getLaunchConfiguration().getType();
					delegate = resolveLaunchDelegate(launch);
				}
				catch (CoreException e) {return false;}
			}
			else if(object instanceof PerspectiveContext) {
				PerspectiveContext context = (PerspectiveContext) object;
				type = context.getLaunchConfigurationType();
				delegate = context.getLaunchDelegate();
			}
			if(fType != null && type != null && fType.getIdentifier().equals(type.getIdentifier())) {
				if(fDelegate == null) {
					return delegate == null;
				}
				else {
					return fDelegate.equals(delegate);
				}
			}
			return super.equals(object);
		}

		@Override
		public int hashCode() {
			if (fType != null) {
				int hash = fType.getIdentifier().hashCode();
				if (fDelegate != null) {
					hash += fDelegate.hashCode();
				}
				return hash;
			}
			return super.hashCode();
		}

		public ILaunchConfigurationType getLaunchConfigurationType() {return fType;}
		public ILaunchDelegate getLaunchDelegate() {return fDelegate;}

		public Map<Set<String>, String> getPersepctiveMap() {
			return fPerspectives;
		}

		/**
		 * Creates a new mapping of the specified perspective id to the specified mode set.
		 * If a mapping for the modeset already exists it is over-written.
		 * @param modes the set of modes
		 * @param pid the id of the perspective
		 */
		public void setPerspective(Set<String> modes, String pid) {
			if(fPerspectives == null) {
				fPerspectives = new HashMap<>();
			}
			fPerspectives.put(modes, pid);
		}

		/**
		 * Returns the perspective id associated with the given mode set
		 * @param modes the set of mode
		 * @return the perspective id associated with the given mode set, or
		 * <code>null</code>, if there isn't one
		 */
		public String getPerspective(Set<String> modes) {
			if(fPerspectives != null) {
				return fPerspectives.get(modes);
			}
			return null;
		}
	}

	/**
	 * Use a customized UI job so that nested jobs with a scheduling rule are
	 * not prevented from running.
	 * See bug 377593
	 */
	private abstract class MyUIJob extends Job {
		public MyUIJob(String name) {
			super(name);
			setSystem(true);
			setPriority(Job.INTERACTIVE);
			setRule(AsynchronousSchedulingRuleFactory.getDefault().newSerialPerObjectRule(this));
		}

		@Override
		protected IStatus run(final IProgressMonitor monitor) {
	        if (monitor.isCanceled()) {
				return Status.CANCEL_STATUS;
			}
	        Display asyncDisplay = DebugUIPlugin.getStandardDisplay();
	        if (asyncDisplay == null || asyncDisplay.isDisposed()) {
	            return Status.CANCEL_STATUS;
	        }
	        asyncDisplay.asyncExec(new Runnable() {
	            @Override
				public void run() {
	                IStatus result = null;
	                Throwable throwable = null;
	                try {
	                    if (monitor.isCanceled()) {
							result = Status.CANCEL_STATUS;
						} else {
	                        result = runInUIThread(monitor);
	                    }

	                } catch(Throwable t){
	                	throwable = t;
	                } finally {
	                    if (result == null) {
							result = new Status(IStatus.ERROR,
	                                PlatformUI.PLUGIN_ID, IStatus.ERROR,
	                                LaunchConfigurationsMessages.PerspectiveManager_Error_1,
	                                throwable);
						}
	                    done(result);
	                }
	            }
	        });
	        return Job.ASYNC_FINISH;
		}

	    public abstract IStatus runInUIThread(IProgressMonitor monitor);

	}

	/**
	 * A listing of <code>PerspectiveContext</code>s
	 *
	 * @since 3.3
	 */
	private Set<PerspectiveContext> fPerspectiveContexts = null;

	/**
	 * id for the 'delegate' attribute
	 *
	 * @since 3.3
	 */
	public static final String ATTR_DELEGATE_ID = "delegate"; //$NON-NLS-1$

	/**
	 * Flag used to indicate that the user is already being prompted to
	 * switch perspectives. This flag allows us to not open multiple
	 * prompts at the same time.
	 */
	private boolean fPrompting;

    /**
     * Maps each launch to its perspective context activation. These
     * are disabled when a launch terminates.
     */
	private Map<ILaunch, IContextActivation[]> fLaunchToContextActivations = new HashMap<>();

	/**
	 * Called by the debug ui plug-in on startup.
	 * The perspective manager starts listening for
	 * launches to be registered.
	 */
	public void startup() {
		DebugUIPlugin.getDefault().addSaveParticipant(this);
		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
		initPerspectives();
	}

	/**
	 * Called by the debug ui plug-in on shutdown.
	 * The perspective manager de-registers as a
	 * launch listener.
	 */
	public void shutdown() {
		DebugUIPlugin.getDefault().removeSaveParticipant(this);
		DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
	}

	/**
	 * If there are no launches, remove the Suspend Trigger Listener
	 *
	 * @see ILaunchListener#launchRemoved(ILaunch)
	 */
	@Override
	public synchronized void launchRemoved(final ILaunch launch) {
        ISuspendTrigger trigger = launch.getAdapter(ISuspendTrigger.class);
        if (trigger != null) {
            trigger.removeSuspendTriggerListener(this);
        }
        Runnable r= new Runnable() {
			@Override
			public void run() {
		        IContextActivation[] activations = fLaunchToContextActivations.remove(launch);
		        if (activations != null) {
		        	for (int i = 0; i < activations.length; i++) {
						IContextActivation activation = activations[i];
						activation.getContextService().deactivateContext(activation);
					}
		        }
			}
		};
		async(r);
	}

	/**
	 * Do nothing.
	 *
	 * @see ILaunchListener#launchChanged(ILaunch)
	 */
	@Override
	public void launchChanged(ILaunch launch) {}

	/**
	 * Switch to the perspective specified by the
	 * launch configuration.
	 *
	 * @see ILaunchListener#launchAdded(ILaunch)
	 */
	@Override
	public synchronized void launchAdded(ILaunch launch) {
        ISuspendTrigger trigger = launch.getAdapter(ISuspendTrigger.class);
        if (trigger != null) {
            trigger.addSuspendTriggerListener(this);
        }
		String perspectiveId = null;
		// check event filters
		try {
			perspectiveId = getPerspectiveId(launch);
		}
		catch (CoreException e) {
			String name = DebugUIPlugin.getModelPresentation().getText(launch);
			switchFailed(e, name);
		}
		// don't switch if a private config
		ILaunchConfiguration configuration = launch.getLaunchConfiguration();
		if (configuration != null) {
			if (!LaunchConfigurationManager.isVisible(configuration)) {
				perspectiveId = null;
			}
		}
		final String id = perspectiveId;
		// switch
		Job switchJob = new MyUIJob("Perspective Switch Job") { //$NON-NLS-1$
			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				IWorkbenchWindow window = getWindowForPerspective(id);
				if (id != null && window != null && shouldSwitchPerspective(window, id, IInternalDebugUIConstants.PREF_SWITCH_TO_PERSPECTIVE)) {
					switchToPerspective(window, id);
				}
				return Status.OK_STATUS;
			}
		};
		switchJob.setSystem(true);
		switchJob.setPriority(Job.INTERACTIVE);
		//switchJob.setRule(AsynchronousSchedulingRuleFactory.getDefault().newSerialPerObjectRule(this));
		switchJob.schedule();
	}


	/**
	 * Switches to the specified perspective
	 *
	 * @param id perspective identifier
	 */
	protected void switchToPerspective(IWorkbenchWindow window, String id) {
		try {
			// don't loose the focus dialog if there is one
			Shell dialog = getModalDialogOpen(window.getShell());
			window.getWorkbench().showPerspective(id, window);
			if (dialog != null) {
				dialog.setFocus();
			}
		} catch (WorkbenchException e) {
			DebugUIPlugin.errorDialog(DebugUIPlugin.getShell(),
			LaunchConfigurationsMessages.PerspectiveManager_Error_1,
 MessageFormat.format(LaunchConfigurationsMessages.PerspectiveManager_Unable_to_switch_to_perspective___0__2, new Object[] { id }),
			e);
		}
	}

	/**
	 * Utility method to submit an asynchronous runnable to the UI
	 */
	protected void async(Runnable r) {
		Display d = DebugUIPlugin.getStandardDisplay();
		if (d != null && !d.isDisposed()) {
			d.asyncExec(r);
		}
	}

	/**
	 * Utility method to submit a synchronous runnable to the UI
	 */
	protected void sync(Runnable r) {
		Display d = DebugUIPlugin.getStandardDisplay();
		if (d != null && !d.isDisposed()) {
			d.syncExec(r);
		}
	}

	/**
	 * Reports failure to switch perspectives to the user
	 *
	 * @param status exception status describing failure
	 * @param launchName the name of the launch that the
	 *  failure is associated with
	 */
	protected void switchFailed(final Throwable t, final String launchName) {
		sync(new Runnable() {
			@Override
			public void run() {
				DebugUIPlugin.errorDialog(DebugUIPlugin.getShell(), LaunchConfigurationsMessages.PerspectiveManager_Error_1,
 MessageFormat.format(LaunchConfigurationsMessages.PerspectiveManager_Unable_to_switch_perpsectives_as_specified_by_launch___0__4, new Object[] { launchName }),
				 t);
			}});
	}

	/**
	 * A breakpoint has been hit. Carry out perspective switching
	 * as appropriate for the given debug event.
	 *
	 * @param event the suspend event
	 */
	private void handleBreakpointHit(final ILaunch launch) {

		String perspectiveId = null;
		try {
			perspectiveId = getPerspectiveId(launch);
		}
		catch (CoreException e) {DebugUIPlugin.log(e);}
		// if no perspective specified, always switch to debug
		// perspective

		// this has to be done in an async, such that the workbench
		// window can be accessed
		final String targetId = perspectiveId;
		Job switchJob = new MyUIJob("Perspective Switch Job") { //$NON-NLS-1$
			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				IWorkbenchWindow window = null;
				if (targetId != null) {
					// get the window to open the perspective in
					window = getWindowForPerspective(targetId);
					if (window == null) {
						return Status.OK_STATUS;
					}

					// switch the perspective if user preference is set
					if (shouldSwitchPerspective(window, targetId, IInternalDebugUIConstants.PREF_SWITCH_PERSPECTIVE_ON_SUSPEND)) {
						switchToPerspective(window, targetId);
						window = getWindowForPerspective(targetId);
						if (window == null) {
							return Status.OK_STATUS;
						}
					}

					// make sure the shell is active
					Shell shell= window.getShell();
					if (shell != null) {
						if (DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugUIConstants.PREF_ACTIVATE_WORKBENCH)) {
							Shell dialog = getModalDialogOpen(shell);
							if (shell.getMinimized()) {
								shell.setMinimized(false);
								if (dialog != null) {
									dialog.setFocus();
								}
							}
							// If a model dialog is open on the shell, don't activate it
							if (dialog == null) {
								shell.forceActive();
							}
						}
					}

					// Activate a context for the launch
					Object ca = fLaunchToContextActivations.get(launch);
					if (ca == null) {
						ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
						if (launchConfiguration != null) {
							try {
								String type = launchConfiguration.getType().getIdentifier();
								ViewContextService service = ViewContextManager.getDefault().getService(window);
								if (service != null) {
									IContextService contextServce = PlatformUI.getWorkbench().getAdapter(IContextService.class);
									String[] ids = service.getEnabledPerspectives();
									IContextActivation[] activations = new IContextActivation[ids.length];
									for (int i = 0; i < ids.length; i++) {
										// Include the word '.internal.' so the context is filtered from the key binding pref page (Bug 144019) also see ViewContextService.contextActivated()
										Context context = contextServce.getContext(type + ".internal." + ids[i]); //$NON-NLS-1$
										if (!context.isDefined()) {
											context.define(context.getId(), null, null);
										}
										IContextActivation activation = contextServce.activateContext(context.getId());
										activations[i] = activation;
									}
									fLaunchToContextActivations.put(launch, activations);
								}
							} catch (CoreException e) {
								DebugUIPlugin.log(e);
							}
						}
					}

				}
				if (window != null && DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IInternalDebugUIConstants.PREF_ACTIVATE_DEBUG_VIEW)) {
					ViewContextService service = ViewContextManager.getDefault().getService(window);
					service.showViewQuiet(IDebugUIConstants.ID_DEBUG_VIEW);
				}
				return Status.OK_STATUS;
			}
		};

		switchJob.setSystem(true);
		switchJob.setPriority(Job.INTERACTIVE);
		switchJob.setRule(AsynchronousSchedulingRuleFactory.getDefault().newSerialPerObjectRule(this));
		switchJob.schedule();
	}

	/**
	 * Returns a modal dialog currently open on the given shell or <code>null</code> if none.
	 *
	 * @param shell shell to check
	 * @return a modal dialog currently open on the given shell or <code>null</code> if none
	 */
	private Shell getModalDialogOpen(Shell shell) {
		Shell[] shells = shell.getShells();
		for (int i = 0; i < shells.length; i++) {
			Shell dialog = shells[i];
			if ((dialog.getStyle() & (SWT.APPLICATION_MODAL | SWT.PRIMARY_MODAL | SWT.SYSTEM_MODAL)) > 0) {
				return dialog;
			}
		}
		return null;
	}

	/**
	 * Returns the workbench window in which the given perspective
	 * should be shown. First, check the current window to see if it
	 * is already showing the perspective. Then check any other windows.
	 *
	 * @param perspectiveId the perspective identifier
	 * @return which window the given perspective should be shown in
	 *  or <code>null</code> if there are no windows available
	 */
	private IWorkbenchWindow getWindowForPerspective(String perspectiveId) {
		IWorkbenchWindow window = DebugUIPlugin.getActiveWorkbenchWindow();
		if (isWindowShowingPerspective(window, perspectiveId)) {
			return window;
		}
		IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
		for (int i = 0; i < windows.length; i++) {
			window = windows[i];
			if (isWindowShowingPerspective(window, perspectiveId)) {
				return window;
			}
		}
		window = DebugUIPlugin.getActiveWorkbenchWindow();
		if (window != null) {
			return window;
		}
		if (windows.length > 0) {
			return windows[0];
		}
		return null;
	}

	/**
	 * Returns if the specified window is showing the perspective denoted by the specified id
	 * @param window the window to query
	 * @param perspectiveId the perspective to ask about
	 * @return true if the specified window is showing the perspective, false otherwise
	 */
	private boolean isWindowShowingPerspective(IWorkbenchWindow window, String perspectiveId) {
		if (window != null) {
			IWorkbenchPage page = window.getActivePage();
			if (page != null) {
				IPerspectiveDescriptor perspectiveDescriptor = page.getPerspective();
				if (perspectiveDescriptor != null && perspectiveDescriptor.getId().equals(perspectiveId)) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Returns whether or not the user wishes to switch to the specified
	 * perspective when a launch occurs.
	 *
	 * @param perspectiveName the name of the perspective that will be presented
	 *  to the user for confirmation if they've asked to be prompted about
	 *  perspective switching
	 * @param message a message to be presented to the user. This message is expected to
	 *  contain a slot for the perspective name to be inserted ("{0}").
	 * @param preferenceKey the preference key of the perspective switching preference
	 * @return whether or not the user wishes to switch to the specified perspective
	 *  automatically
	 */
	private boolean shouldSwitchPerspective(IWorkbenchWindow window, String perspectiveId, String preferenceKey) {
		if (isCurrentPerspective(window, perspectiveId)) {
			return false;
		}
		String perspectiveName = getPerspectiveLabel(perspectiveId);
		if (perspectiveName == null) {
			return false;
		}
		String perspectiveDesc = getPerspectiveDescription(perspectiveId);
		Object[] args;
		if (perspectiveDesc != null) {
			args = new String[] { perspectiveName , perspectiveDesc };
		}
		else {
			args = new String[] { perspectiveName };
		}
		String switchPerspective = DebugUIPlugin.getDefault().getPreferenceStore().getString(preferenceKey);
		if (MessageDialogWithToggle.ALWAYS.equals(switchPerspective)) {
			return true;
		} else if (MessageDialogWithToggle.NEVER.equals(switchPerspective)) {
			return false;
		}

		Shell shell= window.getShell();
		if (shell == null || fPrompting) {
			return false;
		}
		fPrompting= true;
		// Activate the shell if necessary so the prompt is visible
		Shell modal = getModalDialogOpen(shell);
		if (shell.getMinimized()) {
			shell.setMinimized(false);
			if (modal != null) {
				modal.setFocus();
			}
		}
		if (DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugUIConstants.PREF_ACTIVATE_WORKBENCH)) {
			if (modal == null) {
				shell.forceActive();
			}
		}
		String message = IInternalDebugCoreConstants.EMPTY_STRING;
		if(IInternalDebugUIConstants.PREF_SWITCH_PERSPECTIVE_ON_SUSPEND.equals(preferenceKey)) {
			if (getPerspectiveDescription(perspectiveId) != null) {
				message = LaunchConfigurationsMessages.PerspectiveManager_suspend_description;
			}
			else {
				message = LaunchConfigurationsMessages.PerspectiveManager_13;
			}
		}
		else if(IInternalDebugUIConstants.PREF_SWITCH_TO_PERSPECTIVE.equals(preferenceKey)) {
			if (getPerspectiveDescription(perspectiveId) != null) {
				message = LaunchConfigurationsMessages.PerspectiveManager_launch_description;
			}
			else {
				message = LaunchConfigurationsMessages.PerspectiveManager_15;
			}
		}
		LinkedHashMap<String, Integer> buttonLabelToId = new LinkedHashMap<>();
		buttonLabelToId.put(LaunchConfigurationsMessages.PerspectiveManager_switch, IDialogConstants.YES_ID);
		buttonLabelToId.put(IDialogConstants.NO_LABEL, IDialogConstants.NO_ID);
		MessageDialogWithToggle dialog = MessageDialogWithToggle.open(MessageDialog.QUESTION, shell, LaunchConfigurationsMessages.PerspectiveManager_12, MessageFormat.format(message, args), null, false, DebugUIPlugin.getDefault().getPreferenceStore(), preferenceKey, SWT.NONE, buttonLabelToId);
		boolean answer = (dialog.getReturnCode() == IDialogConstants.YES_ID);
		synchronized (this) {
			fPrompting= false;
			notifyAll();
		}
		if (isCurrentPerspective(window, perspectiveId)) {
			answer = false;
		}
		return answer;
	}

	/**
	 * Returns whether the given perspective identifier matches the
	 * identifier of the current perspective.
	 *
	 * @param perspectiveId the identifier
	 * @return whether the given perspective identifier matches the
	 *  identifier of the current perspective
	 */
	protected boolean isCurrentPerspective(IWorkbenchWindow window, String perspectiveId) {
		boolean isCurrent= false;
		if (window != null) {
			IWorkbenchPage page = window.getActivePage();
			if (page != null) {
				IPerspectiveDescriptor perspectiveDescriptor = page.getPerspective();
				if (perspectiveDescriptor != null) {
					isCurrent= perspectiveId.equals(perspectiveDescriptor.getId());
				}
			}
		}
		return isCurrent;
	}

	/**
	 * Returns the label of the perspective with the given identifier or
	 * <code>null</code> if no such perspective exists.
	 *
	 * @param perspectiveId the identifier
	 * @return the label of the perspective with the given identifier or
	 *  <code>null</code> if no such perspective exists
	 */
	protected String getPerspectiveLabel(String perspectiveId) {
		IPerspectiveDescriptor newPerspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
		if (newPerspective == null) {
			return null;
		}
		return newPerspective.getLabel();
	}


	/**
	 * Returns the label of the perspective with the given identifier or
	 * <code>null</code> if no such perspective exists.
	 *
	 * @param perspectiveId the identifier
	 * @return the label of the perspective with the given identifier or
	 *  <code>null</code> if no such perspective exists
	 */
	protected String getPerspectiveDescription(String perspectiveId) {
		IPerspectiveDescriptor newPerspective = PlatformUI.getWorkbench().getPerspectiveRegistry().findPerspectiveWithId(perspectiveId);
		if (newPerspective == null) {
			return null;
		}
		return newPerspective.getDescription();
	}

	/**
	 * Returns the perspective associated with the
	 * given launch, or <code>null</code> if none.
	 *
	 * @param launch a launch
	 * @return the perspective associated with the launch,
	 * 	or <code>null</code>
	 * @exception CoreException if unable to retrieve a required
	 *  launch configuration attribute
	 */
	protected String getPerspectiveId(ILaunch launch) throws CoreException {
		if (launch == null) {
			return null;
		}
		ILaunchConfiguration config = launch.getLaunchConfiguration();
		if (config == null) {
			return null;
		}
		Set<String> modes = launch.getLaunchConfiguration().getModes();
		modes.add(launch.getLaunchMode());
		String perspectiveId = getLaunchPerspective(config.getType(), modes, resolveLaunchDelegate(launch));
		if (perspectiveId != null && perspectiveId.equals(IDebugUIConstants.PERSPECTIVE_NONE)) {
			perspectiveId = null;
		}
		return perspectiveId;
	}

	/**
	 * Returns the id of the perspective associated with the given type and set of modes. Passing <code>null</code> for
	 * the launch delegate results in the default perspective id being returned (if there is one).
	 * @param type the type we are launching
	 * @param modes the set of modes the type was launched with
	 * @param delegate the delegate performing the launch for this type and modeset
	 * @return the id of the perspective for the given launch configuration type, modeset and launch delegate
	 *
	 * @since 3.3
	 */
	public String getLaunchPerspective(ILaunchConfigurationType type, Set<String> modes, ILaunchDelegate delegate) {
		String id = null;
		PerspectiveContext context = findContext(new PerspectiveContext(type, delegate, modes));
		if(context == null || (context != null && !context.getPersepctiveMap().containsKey(modes))) {
			//try with a null delegate, denoting the perspective for the type
			context = findContext(new PerspectiveContext(type, null, modes));
			if(context == null || (context != null && !context.getPersepctiveMap().containsKey(modes))) {
				//last resort, try the default perspective
				return getDefaultLaunchPerspective(type, delegate, modes);
			}
		}
		if(context != null) {
			id = context.getPerspective(modes);
		}
		return id;
	}

	/**
	 * Returns the perspective to switch to when a configuration of the given type
	 * is launched in the given mode, or <code>null</code> if no switch should take
	 * place.
	 * <p>
	 * This method is equivalent to calling <code>getLaunchPerspective(ILaunchConfigurationType type, Set modes, ILaunchDelegate delegate)</code>,
	 * with the 'mode' parameter comprising a single element set and passing <code>null</code> as the launch delegate.
	 * </p>
	 * @param type launch configuration type
	 * @param mode launch mode identifier
	 * @return perspective identifier or <code>null</code>
	 * @since 3.0
	 */
	public String getLaunchPerspective(ILaunchConfigurationType type, String mode) {
		HashSet<String> modes = new HashSet<>();
		modes.add(mode);
		return getLaunchPerspective(type, modes, null);
	}

	/**
	 * Sets the perspective to switch to when a configuration of the given type
	 * is launched in the given mode. <code>PERSPECTIVE_NONE</code> indicates no
	 * perspective switch should take place. <code>PERSPECTIVE_DEFAULT</code> indicates
	 * a default perspective switch should take place, as defined by the associated
	 * launch tab group extension.
	 * <p>
	 * Calling this method is equivalent to calling <code>setLaunchPerspective(ILaunchConfigurationType type, Set modes, ILaunchDelegate delegate, String perspectiveid)</code>,
	 * with the parameter 'mode' used in the set modes, and null passed as the delegate
	 * </p>
	 * @param type launch configuration type
	 * @param mode launch mode identifier
	 * @param perspective identifier, <code>PERSPECTIVE_NONE</code>, or
	 *   <code>PERSPECTIVE_DEFAULT</code>
	 * @since 3.0
	 */
	public void setLaunchPerspective(ILaunchConfigurationType type, String mode, String perspective) {
		HashSet<String> modes = new HashSet<>();
		modes.add(mode);
		setLaunchPerspective(type, modes, null, perspective);
	}

	/**
	 * Sets the perspective that should be switched to when a configuration of the given type is launched with the
	 * specified modes set by the given launch delegate.
	 * <p>
	 * Passing <code>null</code> as a launch delegate will set the default perspective switch for that type and modeset, where
	 * <code>PERSPECTIVE_NONE</code> indicates no perspective switch should take place.
	 * </p>
	 * @param type the type to set a perspective context for
	 * @param modes the set of modes
	 * @param delegate the delegate, or <code>null</code> if the default perspective should be used
	 *
	 * @since 3.3
	 */
	public void setLaunchPerspective(ILaunchConfigurationType type, Set<String> modes, ILaunchDelegate delegate, String perspectiveid) {
		PerspectiveContext context = new PerspectiveContext(type, delegate, modes);
		String id = null;
		if(!IDebugUIConstants.PERSPECTIVE_NONE.equals(perspectiveid)) {
			if(IDebugUIConstants.PERSPECTIVE_DEFAULT.equals(perspectiveid)) {
				id = getDefaultLaunchPerspective(type, delegate, modes);
			}
			else {
				id = perspectiveid;
			}
		}
		PerspectiveContext item = findContext(context);
		if(item != null) {
			item.setPerspective(modes, id);
		}
		else {
			context.setPerspective(modes, id);
			item = context;
		}
		fPerspectiveContexts.add(item);
	}

	/**
	 * Searches the listing of perspective contexts to see if the specified one already exists
	 * @param context the context to compare
	 * @return the matching <code>PerspectiveContext</code> or <code>null</code> if none
	 *
	 * @since 3.3
	 */
	private PerspectiveContext findContext(PerspectiveContext context) {
		for (PerspectiveContext c : fPerspectiveContexts) {
			if (context.equals(c)) {
				return c;
			}
		}
		return null;
	}

	/**
	 * Generates XML for the user specified perspective settings.
	 *
	 * @return XML
	 * @exception IOException if unable to generate the XML
     * @exception TransformerException if unable to generate the XML
     * @exception ParserConfigurationException if unable to generate the XML
	 */
	private String generatePerspectiveXML() throws ParserConfigurationException, CoreException {
		Document doc = DebugUIPlugin.getDocument();
		Element root = doc.createElement(IConfigurationElementConstants.LAUNCH_PERSPECTIVES);
		doc.appendChild(root);
		Map<Set<String>, String> modesets = null;
		Element element = null;
		String id = null;
		ILaunchConfigurationType type = null;
		ILaunchDelegate delegate = null;
		for (PerspectiveContext context : fPerspectiveContexts) {
			modesets = context.getPersepctiveMap();
			type = context.getLaunchConfigurationType();
			delegate = context.getLaunchDelegate();
			for (Set<String> modes : modesets.keySet()) {
				id = context.getPerspective(modes);
				String defaultId = getDefaultLaunchPerspective(type, delegate, modes);
				if(id == null && defaultId != null) {
					//bug 325557: Override of a default perspective
					id = IDebugUIConstants.PERSPECTIVE_NONE;
				}
				if(id != null && !id.equals(defaultId)) {
					element = doc.createElement(IConfigurationElementConstants.LAUNCH_PERSPECTIVE);
					element.setAttribute(IConfigurationElementConstants.MODE, createModesetString(modes));
					if(delegate != null) {
						element.setAttribute(ATTR_DELEGATE_ID, delegate.getId());
					}
					element.setAttribute(IConfigurationElementConstants.CONFIGURATION_TYPES, type.getIdentifier());
					element.setAttribute(IConfigurationElementConstants.PERSPECTIVE, id);
					root.appendChild(element);
				}
			}

		}
		return DebugPlugin.serializeDocument(doc);
	}

	/**
	 * Returns the default perspective to switch to when a configuration of the given type is launched by the specified
	 * launch delegate in the given mode set, or <code>null</code> if none
	 * @param type the type
	 * @param delegate the associated delegate, or <code>null</code> to specify that the default perspective id for that given type and mode set should be returned
	 * @param modes the set of modes this applies to
	 * @return the default perspective id for the given type, delegate and mode set combination, or <code>null</code> if none
	 *
	 * @since 3.3
	 */
	public String getDefaultLaunchPerspective(ILaunchConfigurationType type, ILaunchDelegate delegate, Set<String> modes) {
		String id = null;
		if(delegate != null) {
			id = delegate.getPerspectiveId(modes);
		}
		if(id == null) {
			LaunchConfigurationTabGroupExtension extension = LaunchConfigurationPresentationManager.getDefault().getExtension(type.getIdentifier(), modes);
			if (extension != null) {
				id = extension.getPerspective(modes);
				if (id == null) {
					if (modes.contains(ILaunchManager.DEBUG_MODE)) {
						id = IDebugUIConstants.ID_DEBUG_PERSPECTIVE;
					}
				}
			}
		}
		return id;
	}

	/**
	 * Resolves the <code>ILaunchDelegate</code> from the given <code>ILaunch</code>
	 * @param launch the launch
	 * @return
	 * @throws CoreException
	 */
	private ILaunchDelegate resolveLaunchDelegate(ILaunch launch) throws CoreException {
		Set<String> modes = launch.getLaunchConfiguration().getModes();
		modes.add(launch.getLaunchMode());
		ILaunchConfigurationType type = launch.getLaunchConfiguration().getType();
		ILaunchDelegate[] delegates = LaunchConfigurationManager.filterLaunchDelegates(type, modes);
		ILaunchDelegate delegate = null;
		if(delegates.length == 1) {
			delegate = delegates[0];
		}
		else if(delegates.length > 1) {
			delegate = launch.getLaunchConfiguration().getPreferredDelegate(modes);
			if(delegate == null) {
				delegate = type.getPreferredDelegate(modes);
			}
		}
		return delegate;
	}

	/**
	 * Initialize the preference set with settings from user preferences
	 */
	private void initPerspectives() {
		if(fPerspectiveContexts == null) {
			fPerspectiveContexts = new HashSet<>();
			String xml = DebugUIPlugin.getDefault().getPreferenceStore().getString(IInternalDebugUIConstants.PREF_LAUNCH_PERSPECTIVES);
			if (xml != null && xml.length() > 0) {
				try {
					Element root = DebugPlugin.parseDocument(xml);
					NodeList list = root.getChildNodes();
					LaunchManager lm = (LaunchManager) DebugPlugin.getDefault().getLaunchManager();
					ILaunchConfigurationType lctype = null;
					ILaunchDelegate ldelegate = null;
					Set<String> modes = null;
					Node node = null;
					Element element = null;
					for (int i = 0; i < list.getLength(); ++i) {
						node = list.item(i);
						if (node.getNodeType() == Node.ELEMENT_NODE) {
							element = (Element) node;
							String nodeName = element.getNodeName();
							if (nodeName.equalsIgnoreCase(IConfigurationElementConstants.LAUNCH_PERSPECTIVE)) {
								String type = element.getAttribute(IConfigurationElementConstants.CONFIGURATION_TYPES);
								String mode = element.getAttribute(IConfigurationElementConstants.MODE);
								String perspective = element.getAttribute(IConfigurationElementConstants.PERSPECTIVE);
								String delegate = element.getAttribute(ATTR_DELEGATE_ID);
								lctype = lm.getLaunchConfigurationType(type);
								ldelegate = lm.getLaunchDelegate(delegate);
								modes = parseModes(mode);
								if(lctype != null && !modes.isEmpty() && !IInternalDebugCoreConstants.EMPTY_STRING.equals(perspective)) {
									setLaunchPerspective(lctype, modes, ldelegate, perspective);
								}
							}
						}
					}
				}
				catch (CoreException e) {DebugUIPlugin.log(e);}
			}
		}
	}

	/**
	 * Parses a string argument into a set of modes
	 * @param modes the string to parse
	 * @return a set of modes parsed from the specified string of the empty set, never null
	 *
	 * @since 3.3
	 */
	private Set<String> parseModes(String modes) {
		HashSet<String> modeset = new HashSet<>();
		String[] ms = modes.split(","); //$NON-NLS-1$
		for(int i = 0; i < ms.length; i++) {
			modeset.add(ms[i].trim());
		}
		return modeset;
	}

	/**
	 * Creates a standard comma separated list of the modes from the specified
	 * set
	 *
	 * @param modes the set to write to string
	 * @return the mode set as a string
	 */
	private String createModesetString(Set<String> modes) {
		String str = IInternalDebugCoreConstants.EMPTY_STRING;
		if(modes != null) {
			for (Iterator<String> iter = modes.iterator(); iter.hasNext();) {
				str += iter.next();
				if(iter.hasNext()) {
					str += ","; //$NON-NLS-1$
				}
			}
		}
		return str;
	}

	/**
	 * Schedules the given job after perspective switching is complete, or
	 * immediately if a perspective switch is not in progress.
	 *
	 * @param job job to run after perspective switching
	 */
	public void schedulePostSwitch(Job job) {
		job.setRule(AsynchronousSchedulingRuleFactory.getDefault().newSerialPerObjectRule(this));
		job.schedule();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.ui.contexts.ISuspendTriggerListener#suspended(org.eclipse.debug.core.ILaunch, java.lang.Object)
	 */
	@Override
	public void suspended(ILaunch launch, Object context) {
		handleBreakpointHit(launch);
	}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#doneSaving(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void doneSaving(ISaveContext context) {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#prepareToSave(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void prepareToSave(ISaveContext context) throws CoreException {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#rollback(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void rollback(ISaveContext context) {}

	/**
	 * @see org.eclipse.core.resources.ISaveParticipant#saving(org.eclipse.core.resources.ISaveContext)
	 */
	@Override
	public void saving(ISaveContext context) throws CoreException {
		try {
			DebugUIPlugin.getDefault().getPreferenceStore().putValue(IInternalDebugUIConstants.PREF_LAUNCH_PERSPECTIVES, generatePerspectiveXML());
		}   catch (ParserConfigurationException e) {
			throw new CoreException(DebugUIPlugin.newErrorStatus("Exception occurred while generating launch perspectives preference XML", e)); //$NON-NLS-1$
		}
	}
}
