/******************************************************************************* * Copyright (c) 2005, 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 * *******************************************************************************/ package org.eclipse.dltk.debug.ui; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.ILaunchConfigurationTab; import org.eclipse.dltk.debug.core.DLTKDebugPlugin; import org.eclipse.dltk.debug.core.model.IScriptVariable; import org.eclipse.dltk.internal.debug.core.model.HotCodeReplaceManager; import org.eclipse.dltk.internal.debug.ui.ScriptDebugOptionsManager; import org.eclipse.dltk.internal.debug.ui.ScriptHotCodeReplaceListener; import org.eclipse.dltk.internal.debug.ui.log.ScriptDebugLogManager; import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin; import org.eclipse.dltk.ui.DLTKUIPlugin; import org.eclipse.dltk.ui.viewsupport.ImageDescriptorRegistry; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.preference.IPreferenceNode; import org.eclipse.jface.preference.IPreferencePage; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.preference.PreferenceManager; import org.eclipse.jface.preference.PreferenceNode; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.window.Window; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsoleListener; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.texteditor.IDocumentProvider; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class DLTKDebugUIPlugin extends AbstractUIPlugin { // The plug-in ID public static final String PLUGIN_ID = "org.eclipse.dltk.debug.ui"; //$NON-NLS-1$ private ImageDescriptorRegistry fImageDescriptorRegistry; // The shared instance private static DLTKDebugUIPlugin plugin; // Map of InterpreterInstallTypeIDs to IConfigurationElements protected Map<String, IConfigurationElement> fInterpreterInstallTypePageMap; protected Map<RGB, Color> fColorTable = new HashMap<>(10); /** * Whether this plugin is in the process of shutting down. */ private boolean fShuttingDown = false; private ScriptHotCodeReplaceListener fHCRListener; private HashMap<String, ScriptDebugModelPresentation> fPresentations = new HashMap<>(); // private Object fUtilPresentation; /** * Returns the image descriptor registry used for this plugin. */ public static ImageDescriptorRegistry getImageDescriptorRegistry() { if (getDefault().fImageDescriptorRegistry == null) { getDefault().fImageDescriptorRegistry = new ImageDescriptorRegistry(); } return getDefault().fImageDescriptorRegistry; } public DLTKDebugUIPlugin() { plugin = this; } @Override public void start(BundleContext context) throws Exception { super.start(context); ILaunchManager launchManager = DebugPlugin.getDefault() .getLaunchManager(); launchManager.addLaunchListener(DebugConsoleManager.getInstance()); launchManager.addLaunchListener(ScriptDebugLogManager.getInstance()); Platform.getAdapterManager().registerAdapters( ScriptDebugElementAdapterFactory.getInstance(), IScriptVariable.class); ScriptDebugOptionsManager.getDefault().startup(); // Special listener that prints command line on the console // TODO: add user preferences ConsolePlugin.getDefault().getConsoleManager() .addConsoleListener(new IConsoleListener() { @Override public void consolesAdded( org.eclipse.ui.console.IConsole[] consoles) { for (int i = 0; i < consoles.length; ++i) { if (consoles[i] instanceof org.eclipse.debug.ui.console.IConsole) { org.eclipse.debug.ui.console.IConsole console = (org.eclipse.debug.ui.console.IConsole) consoles[i]; org.eclipse.ui.console.IOConsoleOutputStream stream = console .getStream( IDebugUIConstants.ID_STANDARD_OUTPUT_STREAM); if (stream != null) { String cmdLine = console.getProcess() .getLaunch().getAttribute( DLTKLaunchingPlugin.LAUNCH_COMMAND_LINE); if (cmdLine != null) { // try { stream.write(cmdLine.trim()); // stream.write("\n"); stream.flush(); } // catch (IOException e) { // DLTKDebugUIPlugin.log(e); } } } } } } @Override public void consolesRemoved( org.eclipse.ui.console.IConsole[] consoles) { } }); fHCRListener = new ScriptHotCodeReplaceListener(); HotCodeReplaceManager.getDefault() .addHotCodeReplaceListener(fHCRListener); DLTKDebugPlugin.setSourceOffsetRetriever( (frame, lineNumber, column, isEndOffset) -> { final ILaunch launch = frame.getLaunch(); final ISourceLocator sourceLocator = launch .getSourceLocator(); final Object object = sourceLocator.getSourceElement(frame); if (object instanceof IFile) { final IDocumentProvider provider = DLTKUIPlugin .getDocumentProvider(); final IDocument document = provider.getDocument( new FileEditorInput((IFile) object)); if (document != null) { try { if (column >= 0) { return document.getLineOffset( lineNumber - 1) + column; } else { if (!isEndOffset) { return document .getLineOffset(lineNumber - 1); } else { final IRegion region = document .getLineInformation( lineNumber - 1); return region.getOffset() + region.getLength(); } } } catch (BadLocationException e) { // ignore } } } return -1; }); } @Override public void stop(BundleContext context) throws Exception { try { DLTKDebugPlugin.setSourceOffsetRetriever(null); HotCodeReplaceManager.getDefault() .removeHotCodeReplaceListener(fHCRListener); setShuttingDown(true); ScriptDebugOptionsManager.getDefault().shutdown(); ScriptDebugElementAdapterFactory.getInstance().dispose(); ILaunchManager launchManager = DebugPlugin.getDefault() .getLaunchManager(); launchManager .removeLaunchListener(DebugConsoleManager.getInstance()); launchManager .removeLaunchListener(ScriptDebugLogManager.getInstance()); Iterator<Color> e = fColorTable.values().iterator(); while (e.hasNext()) e.next().dispose(); } finally { super.stop(context); } } /** * Returns whether this plug-in is in the process of being shutdown. * * @return whether this plug-in is in the process of being shutdown */ public boolean isShuttingDown() { return fShuttingDown; } private void setShuttingDown(boolean value) { this.fShuttingDown = value; } /** * Returns the shared instance * * @return the shared instance */ public static DLTKDebugUIPlugin getDefault() { return plugin; } // UI /** * Returns the active workbench window * * @return the active workbench window */ public static IWorkbenchWindow getActiveWorkbenchWindow() { return getDefault().getWorkbench().getActiveWorkbenchWindow(); } /** * Returns the active workbench shell or <code>null</code> if none * * @return the active workbench shell or <code>null</code> if none */ public static Shell getActiveWorkbenchShell() { IWorkbenchWindow window = getActiveWorkbenchWindow(); if (window != null) { return window.getShell(); } return null; } /** * Returns the standard display to be used. The method first checks, if the * thread calling this method has an associated display. If so, this display * is returned. Otherwise the method returns the default display. */ public static Display getStandardDisplay() { return DLTKUIPlugin.getStandardDisplay(); } /** * Convenience method which returns the unique identifier of this plugin. */ public static String getUniqueIdentifier() { return PLUGIN_ID; } /** * Displays the given preference page. * * @param id * pref page id * @param page * pref page */ public static void showPreferencePage(String id, IPreferencePage page) { final IPreferenceNode targetNode = new PreferenceNode(id, page); PreferenceManager manager = new PreferenceManager(); manager.addToRoot(targetNode); final PreferenceDialog dialog = new PreferenceDialog( DLTKDebugUIPlugin.getActiveWorkbenchShell(), manager); final boolean[] result = new boolean[] { false }; BusyIndicator.showWhile(DLTKDebugUIPlugin.getStandardDisplay(), () -> { dialog.create(); dialog.setMessage(targetNode.getLabelText()); result[0] = (dialog.open() == Window.OK); }); } /** * Logs the specified status with this plug-in's log. * * @param status * status to log */ public static void log(IStatus status) { getDefault().getLog().log(status); } /** * Logs an internal error with the specified message. * * @param message * the error message to log */ public static void logErrorMessage(String message) { log(new Status(IStatus.ERROR, getUniqueIdentifier(), IDLTKDebugUIConstants.INTERNAL_ERROR, message, null)); } /** * Logs an internal error with the specified throwable * * @param e * the exception to be logged */ public static void log(Throwable e) { log(new Status(IStatus.ERROR, getUniqueIdentifier(), IDLTKDebugUIConstants.INTERNAL_ERROR, Messages.DLTKDebugUIPlugin_internalError, e)); } public static void errorDialog(String message, IStatus status) { log(status); Shell shell = getActiveWorkbenchShell(); if (shell != null) { ErrorDialog.openError(shell, "DebugUIM0essages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$ message, status); } } /** * Utility method with conventions */ public static void errorDialog(String message, Throwable t) { log(t); Shell shell = getActiveWorkbenchShell(); if (shell != null) { IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), IDLTKDebugUIConstants.INTERNAL_ERROR, "Error logged from DLTK Debug UI: ", t); //$NON-NLS-1$ ErrorDialog.openError(shell, "DebugUIMessages.JDIDebugUIPlugin_Error_1", //$NON-NLS-1$ message, status); } } /** * Return an object that implements <code>ILaunchConfigurationTab</code> for * the specified Interpreter install type ID. */ public ILaunchConfigurationTab getInterpreterInstallTypePage( String InterpreterInstallTypeID) { if (fInterpreterInstallTypePageMap == null) { initializeInterpreterInstallTypePageMap(); } IConfigurationElement configElement = fInterpreterInstallTypePageMap .get(InterpreterInstallTypeID); ILaunchConfigurationTab tab = null; if (configElement != null) { try { tab = (ILaunchConfigurationTab) configElement .createExecutableExtension("class"); //$NON-NLS-1$ } catch (CoreException ce) { log(new Status(IStatus.ERROR, getUniqueIdentifier(), IDLTKDebugUIConstants.INTERNAL_ERROR, "DebugUIMessages.JDIDebugUIPlugin_An_error_occurred_retrieving_a_InterpreterInstallType_page_1", //$NON-NLS-1$ ce)); } } return tab; } protected void initializeInterpreterInstallTypePageMap() { fInterpreterInstallTypePageMap = new HashMap<>( 10); IExtensionPoint extensionPoint = Platform.getExtensionRegistry() .getExtensionPoint(getUniqueIdentifier(), IDLTKDebugUIConstants.EXTENSION_POINT_INTERPRETER_INSTALL_TYPE_PAGE); IConfigurationElement[] infos = extensionPoint .getConfigurationElements(); for (int i = 0; i < infos.length; i++) { String id = infos[i].getAttribute("interpreterInstallTypeID"); //$NON-NLS-1$ fInterpreterInstallTypePageMap.put(id, infos[i]); } } public static IWorkbenchPage getActivePage() { IWorkbenchWindow w = getActiveWorkbenchWindow(); if (w != null) { return w.getActivePage(); } return null; } private static ScriptDebugModelPresentation loadDebugModelPresentation( String modelId) { IExtensionPoint point = Platform.getExtensionRegistry() .getExtensionPoint(IDebugUIConstants.PLUGIN_ID, IDebugUIConstants.ID_DEBUG_MODEL_PRESENTATION); if (point != null) { IExtension[] extensions = point.getExtensions(); for (int i = 0; i < extensions.length; i++) { IExtension extension = extensions[i]; IConfigurationElement[] configElements = extension .getConfigurationElements(); for (int j = 0; j < configElements.length; j++) { IConfigurationElement elt = configElements[j]; String id = elt.getAttribute("id"); //$NON-NLS-1$ if (id != null && id.equals(modelId)) { try { return (ScriptDebugModelPresentation) elt .createExecutableExtension("class"); //$NON-NLS-1$ } catch (CoreException e) { DLTKDebugUIPlugin.log(e); } } } } } return null; } public synchronized ScriptDebugModelPresentation getModelPresentation( String modelId) { if (!fPresentations.containsKey(modelId)) { fPresentations.put(modelId, loadDebugModelPresentation(modelId)); } return fPresentations.get(modelId); } public Color getColor(RGB rgb) { Color color = fColorTable.get(rgb); if (color == null) { color = new Color(Display.getCurrent(), rgb); fColorTable.put(rgb, color); } return color; } }