1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.debug.ui;
15 
16 
17 import java.lang.reflect.InvocationTargetException;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 
25 import org.eclipse.core.resources.ISaveContext;
26 import org.eclipse.core.resources.ISaveParticipant;
27 import org.eclipse.core.resources.IWorkspaceRoot;
28 import org.eclipse.core.resources.ResourcesPlugin;
29 import org.eclipse.core.runtime.CoreException;
30 import org.eclipse.core.runtime.IAdapterFactory;
31 import org.eclipse.core.runtime.IAdapterManager;
32 import org.eclipse.core.runtime.IConfigurationElement;
33 import org.eclipse.core.runtime.IExtensionPoint;
34 import org.eclipse.core.runtime.IProgressMonitor;
35 import org.eclipse.core.runtime.IStatus;
36 import org.eclipse.core.runtime.Platform;
37 import org.eclipse.core.runtime.Status;
38 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
39 import org.eclipse.core.runtime.preferences.InstanceScope;
40 import org.eclipse.debug.ui.DebugUITools;
41 import org.eclipse.debug.ui.IDebugModelPresentation;
42 import org.eclipse.debug.ui.IDebugUIConstants;
43 import org.eclipse.debug.ui.ILaunchConfigurationTab;
44 import org.eclipse.jdt.core.IJavaModel;
45 import org.eclipse.jdt.core.IJavaProject;
46 import org.eclipse.jdt.core.IMember;
47 import org.eclipse.jdt.core.IPackageFragment;
48 import org.eclipse.jdt.core.JavaCore;
49 import org.eclipse.jdt.core.JavaModelException;
50 import org.eclipse.jdt.debug.core.IJavaBreakpoint;
51 import org.eclipse.jdt.debug.core.IJavaDebugTarget;
52 import org.eclipse.jdt.debug.core.IJavaHotCodeReplaceListener;
53 import org.eclipse.jdt.debug.core.IJavaStackFrame;
54 import org.eclipse.jdt.debug.core.IJavaThread;
55 import org.eclipse.jdt.debug.core.IJavaThreadGroup;
56 import org.eclipse.jdt.debug.core.IJavaValue;
57 import org.eclipse.jdt.debug.core.IJavaVariable;
58 import org.eclipse.jdt.debug.core.JDIDebugModel;
59 import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
60 import org.eclipse.jdt.internal.debug.ui.breakpoints.ExceptionInspector;
61 import org.eclipse.jdt.internal.debug.ui.breakpoints.JavaBreakpointTypeAdapterFactory;
62 import org.eclipse.jdt.internal.debug.ui.classpath.ClasspathEntryAdapterFactory;
63 import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression;
64 import org.eclipse.jdt.internal.debug.ui.monitors.JavaContendedMonitor;
65 import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwnedMonitor;
66 import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwningThread;
67 import org.eclipse.jdt.internal.debug.ui.monitors.JavaWaitingThread;
68 import org.eclipse.jdt.internal.debug.ui.monitors.MonitorsAdapterFactory;
69 import org.eclipse.jdt.internal.debug.ui.snippeteditor.SnippetFileDocumentProvider;
70 import org.eclipse.jdt.internal.debug.ui.sourcelookup.JavaDebugShowInAdapterFactory;
71 import org.eclipse.jdt.internal.debug.ui.threadgroups.TargetAdapterFactory;
72 import org.eclipse.jdt.internal.debug.ui.threadgroups.ThreadGroupAdapterFactory;
73 import org.eclipse.jdt.internal.debug.ui.variables.ColumnPresentationAdapterFactory;
74 import org.eclipse.jdt.internal.debug.ui.variables.JavaDebugElementAdapterFactory;
75 import org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry;
76 import org.eclipse.jdt.launching.sourcelookup.IJavaSourceLocation;
77 import org.eclipse.jdt.ui.JavaElementLabelProvider;
78 import org.eclipse.jdt.ui.PreferenceConstants;
79 import org.eclipse.jdt.ui.text.JavaTextTools;
80 import org.eclipse.jface.dialogs.ErrorDialog;
81 import org.eclipse.jface.dialogs.MessageDialog;
82 import org.eclipse.jface.operation.IRunnableWithProgress;
83 import org.eclipse.jface.preference.IPreferenceNode;
84 import org.eclipse.jface.preference.IPreferencePage;
85 import org.eclipse.jface.preference.PreferenceDialog;
86 import org.eclipse.jface.preference.PreferenceManager;
87 import org.eclipse.jface.preference.PreferenceNode;
88 import org.eclipse.jface.resource.ImageRegistry;
89 import org.eclipse.jface.window.Window;
90 import org.eclipse.swt.custom.BusyIndicator;
91 import org.eclipse.swt.widgets.Display;
92 import org.eclipse.swt.widgets.Shell;
93 import org.eclipse.ui.IWorkbenchPage;
94 import org.eclipse.ui.IWorkbenchWindow;
95 import org.eclipse.ui.PlatformUI;
96 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
97 import org.eclipse.ui.dialogs.PreferencesUtil;
98 import org.eclipse.ui.plugin.AbstractUIPlugin;
99 import org.eclipse.ui.texteditor.IDocumentProvider;
100 import org.osgi.framework.Bundle;
101 import org.osgi.framework.BundleContext;
102 import org.osgi.service.prefs.BackingStoreException;
103 
104 /**
105  * Plug-in class for the org.eclipse.jdt.debug.ui plug-in.
106  */
107 public class JDIDebugUIPlugin extends AbstractUIPlugin {
108 
109 	/**
110 	 * Unique identifier constant (value <code>"org.eclipse.jdt.debug.ui"</code>)
111 	 * for the JDI Debug plug-in.
112 	 */
113 	private static final String PI_JDI_DEBUG = "org.eclipse.jdt.debug.ui"; //$NON-NLS-1$
114 
115 	/**
116 	 * Id for inspect command.
117 	 *
118 	 * @since 3.3
119 	 */
120 	public static final String COMMAND_INSPECT = "org.eclipse.jdt.debug.ui.commands.Inspect"; //$NON-NLS-1$
121 
122 	/**
123 	 * Java Debug UI plug-in instance
124 	 */
125 	private static JDIDebugUIPlugin fgPlugin;
126 
127 	private IDocumentProvider fSnippetDocumentProvider;
128 
129 	private ImageDescriptorRegistry fImageDescriptorRegistry;
130 
131 	private ActionFilterAdapterFactory fActionFilterAdapterFactory;
132 	private JavaSourceLocationWorkbenchAdapterFactory fSourceLocationAdapterFactory;
133 	private JavaBreakpointWorkbenchAdapterFactory fBreakpointAdapterFactory;
134 
135 	private IDebugModelPresentation fUtilPresentation;
136 
137 	/**
138 	 * Java Debug UI listeners
139 	 */
140 	private IJavaHotCodeReplaceListener fHCRListener;
141 
142 	// Map of VMInstallTypeIDs to IConfigurationElements
143 	protected Map<String, IConfigurationElement> fVmInstallTypePageMap;
144 
145 	/**
146 	 * Whether this plugin is in the process of shutting
147 	 * down.
148 	 */
149 	private boolean fShuttingDown= false;
150 
151 	/**
152 	 * Singleton text tools for debug plug-in.
153 	 */
154 	private JavaTextTools fTextTools = null;
155 
156 	/**
157 	 * @see Plugin()
158 	 */
JDIDebugUIPlugin()159 	public JDIDebugUIPlugin() {
160 		super();
161 		setDefault(this);
162 	}
163 
164 	/**
165 	 * Sets the Java Debug UI plug-in instance
166 	 *
167 	 * @param plugin the plugin instance
168 	 */
setDefault(JDIDebugUIPlugin plugin)169 	private static void setDefault(JDIDebugUIPlugin plugin) {
170 		fgPlugin = plugin;
171 	}
172 
173 	/**
174 	 * Returns the Java Debug UI plug-in instance
175 	 *
176 	 * @return the Java Debug UI plug-in instance
177 	 */
getDefault()178 	public static JDIDebugUIPlugin getDefault() {
179 		return fgPlugin;
180 	}
181 
182 	/**
183 	 * Convenience method which returns the unique identifier of this plugin.
184 	 */
getUniqueIdentifier()185 	public static String getUniqueIdentifier() {
186 		return PI_JDI_DEBUG;
187 	}
188 
189 	/**
190 	 * Logs the specified status with this plug-in's log.
191 	 *
192 	 * @param status status to log
193 	 */
log(IStatus status)194 	public static void log(IStatus status) {
195 		getDefault().getLog().log(status);
196 	}
197 
198 	/**
199 	 * Logs an internal error with the specified message and throwable
200 	 *
201 	 * @param message the error message to log
202 	 * @param e
203 	 *            the exception to be logged
204 	 */
log(String message, Throwable e)205 	public static void log(String message, Throwable e) {
206 		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, e));
207 	}
208 
209 	/**
210 	 * Logs an internal error with the specified throwable
211 	 *
212 	 * @param e the exception to be logged
213 	 */
log(Throwable e)214 	public static void log(Throwable e) {
215 		log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "Internal Error", e)); //$NON-NLS-1$
216 	}
217 
218 	/**
219 	 * Returns the active workbench window
220 	 *
221 	 * @return the active workbench window
222 	 */
getActiveWorkbenchWindow()223 	public static IWorkbenchWindow getActiveWorkbenchWindow() {
224 		return PlatformUI.getWorkbench().getActiveWorkbenchWindow();
225 	}
226 
getActivePage()227 	public static IWorkbenchPage getActivePage() {
228 		IWorkbenchWindow w = getActiveWorkbenchWindow();
229 		if (w != null) {
230 			return w.getActivePage();
231 		}
232 		return null;
233 	}
234 
235 
236 	/**
237 	 * Returns the active workbench shell or <code>null</code> if none
238 	 *
239 	 * @return the active workbench shell or <code>null</code> if none
240 	 */
getActiveWorkbenchShell()241 	public static Shell getActiveWorkbenchShell() {
242 		IWorkbenchWindow window = getActiveWorkbenchWindow();
243 		if (window != null) {
244 			return window.getShell();
245 		}
246 		return null;
247 	}
248 
249 	/* (non-Javadoc)
250 	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#createImageRegistry()
251 	 */
252 	@Override
createImageRegistry()253 	protected ImageRegistry createImageRegistry() {
254 		return JavaDebugImages.getImageRegistry();
255 	}
256 
getSnippetDocumentProvider()257 	public IDocumentProvider getSnippetDocumentProvider() {
258 		if (fSnippetDocumentProvider == null) {
259 			fSnippetDocumentProvider= new SnippetFileDocumentProvider();
260 		}
261 		return fSnippetDocumentProvider;
262 	}
263 
statusDialog(IStatus status)264 	public static void statusDialog(IStatus status) {
265 		switch (status.getSeverity()) {
266 		case IStatus.ERROR:
267 			statusDialog(DebugUIMessages.JDIDebugUIPlugin_Error_1, status);
268 			break;
269 		case IStatus.WARNING:
270 			statusDialog(DebugUIMessages.JDIDebugUIPlugin_0, status);
271 			break;
272 		case IStatus.INFO:
273 			statusDialog(DebugUIMessages.JDIDebugUIPlugin_4, status);
274 			break;
275 		}
276 	}
statusDialog(String title, IStatus status)277 	public static void statusDialog(String title, IStatus status) {
278 		Shell shell = getActiveWorkbenchShell();
279 		if (shell != null) {
280 			switch (status.getSeverity()) {
281 			case IStatus.ERROR:
282 				ErrorDialog.openError(shell, title, null, status);
283 				break;
284 			case IStatus.WARNING:
285 				MessageDialog.openWarning(shell, title, status.getMessage());
286 				break;
287 			case IStatus.INFO:
288 				MessageDialog.openInformation(shell, title, status.getMessage());
289 				break;
290 			}
291 		}
292 	}
293 
294 	/**
295 	 * Creates a new internal error status with the specified message and throwable, then displays
296 	 * it in a status dialog.
297 	 *
298 	 * @param message error message
299 	 * @param t throwable cause or <code>null</code>
300 	 */
errorDialog(String message, Throwable t)301 	public static void errorDialog(String message, Throwable t) {
302 		IStatus status= new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, t);
303 		statusDialog(status);
304 	}
305 
306 	/**
307 	 * Opens an error dialog with the given title and message.
308 	 */
errorDialog(Shell shell, String title, String message, Throwable t)309 	public static void errorDialog(Shell shell, String title, String message, Throwable t) {
310 		IStatus status;
311 		if (t instanceof CoreException) {
312 			status= ((CoreException)t).getStatus();
313 			// if the 'message' resource string and the IStatus' message are the same,
314 			// don't show both in the dialog
315 			if (status != null && message.equals(status.getMessage())) {
316 				message= null;
317 			}
318 		} else {
319 			status= new Status(IStatus.ERROR, getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, "Error within Debug UI: ", t); //$NON-NLS-1$
320 			log(status);
321 		}
322 		ErrorDialog.openError(shell, title, message, status);
323 	}
324 
325 	/**
326 	 * Creates an extension.  If the extension plugin has not
327 	 * been loaded a busy cursor will be activated during the duration of
328 	 * the load.
329 	 *
330 	 * @param element the config element defining the extension
331 	 * @param classAttribute the name of the attribute carrying the class
332 	 * @return the extension object
333 	 */
createExtension(final IConfigurationElement element, final String classAttribute)334 	public static Object createExtension(final IConfigurationElement element, final String classAttribute) throws CoreException {
335 		// If plugin has been loaded create extension.
336 		// Otherwise, show busy cursor then create extension.
337 		Bundle bundle = Platform.getBundle(element.getContributor().getName());
338 		if (bundle.getState() == Bundle.ACTIVE) {
339 			return element.createExecutableExtension(classAttribute);
340 		}
341 
342 		final Object [] ret = new Object[1];
343 		final CoreException [] exc = new CoreException[1];
344 		BusyIndicator.showWhile(null, new Runnable() {
345 			@Override
346 			public void run() {
347 				try {
348 					ret[0] = element.createExecutableExtension(classAttribute);
349 				} catch (CoreException e) {
350 					exc[0] = e;
351 				}
352 			}
353 		});
354 		if (exc[0] != null) {
355 			throw exc[0];
356 		}
357 		return ret[0];
358 	}
359 
360 	/* (non-Javadoc)
361 	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
362 	 */
363 	@Override
start(BundleContext context)364 	public void start(BundleContext context) throws Exception {
365 		super.start(context);
366 		IAdapterManager manager= Platform.getAdapterManager();
367 		fActionFilterAdapterFactory= new ActionFilterAdapterFactory();
368 		manager.registerAdapters(fActionFilterAdapterFactory, IMember.class);
369 		manager.registerAdapters(fActionFilterAdapterFactory, IJavaVariable.class);
370 		manager.registerAdapters(fActionFilterAdapterFactory, IJavaStackFrame.class);
371 		manager.registerAdapters(fActionFilterAdapterFactory, IJavaThread.class);
372 		manager.registerAdapters(fActionFilterAdapterFactory, JavaInspectExpression.class);
373 		fSourceLocationAdapterFactory = new JavaSourceLocationWorkbenchAdapterFactory();
374 		manager.registerAdapters(fSourceLocationAdapterFactory, IJavaSourceLocation.class);
375 		fBreakpointAdapterFactory= new JavaBreakpointWorkbenchAdapterFactory();
376 		manager.registerAdapters(fBreakpointAdapterFactory, IJavaBreakpoint.class);
377         IAdapterFactory typeFactory = new JavaBreakpointTypeAdapterFactory();
378         manager.registerAdapters(typeFactory, IJavaBreakpoint.class);
379 
380         IAdapterFactory monitorFactory = new MonitorsAdapterFactory();
381         manager.registerAdapters(monitorFactory, IJavaThread.class);
382         manager.registerAdapters(monitorFactory, JavaContendedMonitor.class);
383         manager.registerAdapters(monitorFactory, JavaOwnedMonitor.class);
384         manager.registerAdapters(monitorFactory, JavaOwningThread.class);
385         manager.registerAdapters(monitorFactory, JavaWaitingThread.class);
386         manager.registerAdapters(monitorFactory, IJavaStackFrame.class);
387 
388         IAdapterFactory targetFactory = new TargetAdapterFactory();
389         manager.registerAdapters(targetFactory, IJavaDebugTarget.class);
390 
391         IAdapterFactory groupFactory = new ThreadGroupAdapterFactory();
392         manager.registerAdapters(groupFactory, IJavaThreadGroup.class);
393 
394         IAdapterFactory showInFactory = new JavaDebugShowInAdapterFactory();
395         manager.registerAdapters(showInFactory, IJavaStackFrame.class);
396 
397         IAdapterFactory columnFactory = new ColumnPresentationAdapterFactory();
398         manager.registerAdapters(columnFactory, IJavaVariable.class);
399         manager.registerAdapters(columnFactory, IJavaStackFrame.class);
400 
401         IAdapterFactory entryFactory = new ClasspathEntryAdapterFactory();
402         manager.registerAdapters(entryFactory, DefaultProjectClasspathEntry.class);
403 
404         IAdapterFactory variableFactory = new JavaDebugElementAdapterFactory();
405         manager.registerAdapters(variableFactory, IJavaVariable.class);
406         manager.registerAdapters(variableFactory, IJavaValue.class);
407         manager.registerAdapters(variableFactory, JavaInspectExpression.class);
408 
409 		fHCRListener= new JavaHotCodeReplaceListener();
410 		JDIDebugModel.addHotCodeReplaceListener(fHCRListener);
411 
412 		// initialize exception inspector handler
413 		new ExceptionInspector();
414 
415 		ResourcesPlugin.getWorkspace().addSaveParticipant(getUniqueIdentifier(), new ISaveParticipant() {
416 			@Override
417 			public void doneSaving(ISaveContext sc) {}
418 			@Override
419 			public void prepareToSave(ISaveContext sc)	throws CoreException {}
420 			@Override
421 			public void rollback(ISaveContext sc) {}
422 			@Override
423 			public void saving(ISaveContext sc) throws CoreException {
424 				IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(getUniqueIdentifier());
425 				if(prefs != null) {
426 					try {
427 						prefs.flush();
428 					}
429 					catch (BackingStoreException e) {
430 						log(e);
431 					}
432 				}
433 			}
434 		});
435 		JavaDebugOptionsManager.getDefault().startup();
436 	}
437 
438 	/* (non-Javadoc)
439 	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
440 	 */
441 	@Override
stop(BundleContext context)442 	public void stop(BundleContext context) throws Exception {
443 		try {
444 			setShuttingDown(true);
445 			JDIDebugModel.removeHotCodeReplaceListener(fHCRListener);
446 			JavaDebugOptionsManager.getDefault().shutdown();
447 			if (fImageDescriptorRegistry != null) {
448 				fImageDescriptorRegistry.dispose();
449 			}
450 			IAdapterManager manager= Platform.getAdapterManager();
451 			manager.unregisterAdapters(fActionFilterAdapterFactory);
452 			manager.unregisterAdapters(fSourceLocationAdapterFactory);
453 			manager.unregisterAdapters(fBreakpointAdapterFactory);
454 			if (fUtilPresentation != null) {
455 				fUtilPresentation.dispose();
456 			}
457 			if (fTextTools != null) {
458 				fTextTools.dispose();
459 			}
460 			ResourcesPlugin.getWorkspace().removeSaveParticipant(getUniqueIdentifier());
461 		} finally {
462 			super.stop(context);
463 		}
464 	}
465 
466 	/**
467 	 * Returns whether this plug-in is in the process of
468 	 * being shutdown.
469 	 *
470 	 * @return whether this plug-in is in the process of
471 	 *  being shutdown
472 	 */
isShuttingDown()473 	protected boolean isShuttingDown() {
474 		return fShuttingDown;
475 	}
476 
477 	/**
478 	 * Sets whether this plug-in is in the process of
479 	 * being shutdown.
480 	 *
481 	 * @param value whether this plug-in is in the process of
482 	 *  being shutdown
483 	 */
setShuttingDown(boolean value)484 	private void setShuttingDown(boolean value) {
485 		fShuttingDown = value;
486 	}
487 
488 	/**
489 	 * Returns the image descriptor registry used for this plugin.
490 	 */
getImageDescriptorRegistry()491 	public static ImageDescriptorRegistry getImageDescriptorRegistry() {
492 		if (getDefault().fImageDescriptorRegistry == null) {
493 			getDefault().fImageDescriptorRegistry = new ImageDescriptorRegistry();
494 		}
495 		return getDefault().fImageDescriptorRegistry;
496 	}
497 
498 	/**
499 	 * Returns the standard display to be used. The method first checks, if
500 	 * the thread calling this method has an associated display. If so, this
501 	 * display is returned. Otherwise the method returns the default display.
502 	 */
getStandardDisplay()503 	public static Display getStandardDisplay() {
504 		Display display;
505 		display= Display.getCurrent();
506 		if (display == null) {
507 			display= Display.getDefault();
508 		}
509 		return display;
510 	}
511 
512 	/**
513 	 * Returns the currently active workbench window shell or <code>null</code>
514 	 * if none.
515 	 *
516 	 * @return the currently active workbench window shell or <code>null</code>
517 	 */
getShell()518 	public static Shell getShell() {
519 		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
520 		if (window == null) {
521 			IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
522 			if (windows.length > 0) {
523 				return windows[0].getShell();
524 			}
525 		}
526 		else {
527 			return window.getShell();
528 		}
529 		return null;
530 	}
531 
532 	/**
533 	 * Utility method to create and return a selection dialog that allows
534 	 * selection of a specific Java package.  Empty packages are not returned.
535 	 * If Java Projects are provided, only packages found within those projects
536 	 * are included.  If no Java projects are provided, all Java projects in the
537 	 * workspace are considered.
538 	 */
createAllPackagesDialog(Shell shell, IJavaProject[] originals, final boolean includeDefaultPackage)539 	public static ElementListSelectionDialog createAllPackagesDialog(Shell shell, IJavaProject[] originals, final boolean includeDefaultPackage) throws JavaModelException{
540 		final List<IPackageFragment> packageList = new ArrayList<>();
541 		if (originals == null) {
542 			IWorkspaceRoot wsroot= ResourcesPlugin.getWorkspace().getRoot();
543 			IJavaModel model= JavaCore.create(wsroot);
544 			originals= model.getJavaProjects();
545 		}
546 		final IJavaProject[] projects= originals;
547 		final JavaModelException[] exception= new JavaModelException[1];
548 		final boolean[] monitorCanceled = new boolean[] {false};
549 		IRunnableWithProgress r= new IRunnableWithProgress() {
550 			@Override
551 			public void run(IProgressMonitor monitor) {
552 				try {
553 					Set<String> packageNameSet= new HashSet<>();
554 					monitor.beginTask(DebugUIMessages.JDIDebugUIPlugin_Searching_1, projects.length);
555 					for (int i = 0; i < projects.length; i++) {
556 						IPackageFragment[] pkgs= projects[i].getPackageFragments();
557 						for (int j = 0; j < pkgs.length; j++) {
558 							if (monitor.isCanceled()) {
559 								monitorCanceled[0] = true;
560 								return;
561 							}
562 							IPackageFragment pkg = pkgs[j];
563 							if (!pkg.hasChildren() && (pkg.getNonJavaResources().length > 0)) {
564 								continue;
565 							}
566 							String pkgName= pkg.getElementName();
567 							if (!includeDefaultPackage && pkgName.length() == 0) {
568 								continue;
569 							}
570 							if (packageNameSet.add(pkgName)) {
571 								packageList.add(pkg);
572 							}
573 						}
574 						monitor.worked(1);
575 					}
576 					monitor.done();
577 				} catch (JavaModelException jme) {
578 					exception[0]= jme;
579 				}
580 			}
581 		};
582 		try {
583 			PlatformUI.getWorkbench().getProgressService().busyCursorWhile(r);
584 		} catch (InvocationTargetException e) {
585 			JDIDebugUIPlugin.log(e);
586 		} catch (InterruptedException e) {
587 			JDIDebugUIPlugin.log(e);
588 		}
589 		if (exception[0] != null) {
590 			throw exception[0];
591 		}
592 		if (monitorCanceled[0]) {
593 			return null;
594 		}
595 
596 		int flags= JavaElementLabelProvider.SHOW_DEFAULT;
597 		PackageSelectionDialog dialog= new PackageSelectionDialog(shell, new JavaElementLabelProvider(flags));
598 		dialog.setIgnoreCase(false);
599 		dialog.setElements(packageList.toArray()); // XXX inefficient
600 		return dialog;
601 	}
602 
603 	/**
604 	 * Return an object that implements <code>ILaunchConfigurationTab</code> for the
605 	 * specified vm install type ID.
606 	 */
getVMInstallTypePage(String vmInstallTypeID)607 	public ILaunchConfigurationTab getVMInstallTypePage(String vmInstallTypeID) {
608 		if (fVmInstallTypePageMap == null) {
609 			initializeVMInstallTypePageMap();
610 		}
611 		IConfigurationElement configElement = fVmInstallTypePageMap.get(vmInstallTypeID);
612 		ILaunchConfigurationTab tab = null;
613 		if (configElement != null) {
614 			try {
615 				tab = (ILaunchConfigurationTab) configElement.createExecutableExtension("class"); //$NON-NLS-1$
616 			} catch(CoreException ce) {
617 				log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "An error occurred retrieving a VMInstallType page.", ce));  //$NON-NLS-1$
618 			}
619 		}
620 		return tab;
621 	}
622 
initializeVMInstallTypePageMap()623 	protected void initializeVMInstallTypePageMap() {
624 		fVmInstallTypePageMap = new HashMap<>(10);
625 
626 		IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(getUniqueIdentifier(), IJavaDebugUIConstants.EXTENSION_POINT_VM_INSTALL_TYPE_PAGE);
627 		IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
628 		for (int i = 0; i < infos.length; i++) {
629 			String id = infos[i].getAttribute("vmInstallTypeID"); //$NON-NLS-1$
630 			fVmInstallTypePageMap.put(id, infos[i]);
631 		}
632 	}
633 
634 	/**
635 	 * Returns a shared utility Java debug model presentation. Clients should not
636 	 * dispose the presentation.
637 	 *
638 	 * @return a Java debug model presentation
639 	 */
getModelPresentation()640 	public IDebugModelPresentation getModelPresentation() {
641 		if (fUtilPresentation == null) {
642 			fUtilPresentation = DebugUITools.newDebugModelPresentation(JDIDebugModel.getPluginIdentifier());
643 		}
644 		return fUtilPresentation;
645 	}
646 
647 	/**
648 	 * Displays the given preference page.
649 	 *
650 	 * @param id pref page id
651 	 * @param page pref page
652 	 * @deprecated use <code>JDIDebugUIPlugin#showPreferencePage(String pageId)</code>, which uses the <code>PreferenceUtils</code> framework for opening pages.
653 	 */
654 	@Deprecated
showPreferencePage(String id, IPreferencePage page)655 	public static void showPreferencePage(String id, IPreferencePage page) {
656 		final IPreferenceNode targetNode = new PreferenceNode(id, page);
657 
658 		PreferenceManager manager = new PreferenceManager();
659 		manager.addToRoot(targetNode);
660 		final PreferenceDialog dialog = new PreferenceDialog(JDIDebugUIPlugin.getActiveWorkbenchShell(), manager);
661 		final boolean [] result = new boolean[] { false };
662 		BusyIndicator.showWhile(JDIDebugUIPlugin.getStandardDisplay(), new Runnable() {
663 			@Override
664 			public void run() {
665 				dialog.create();
666 				dialog.setMessage(targetNode.getLabelText());
667 				result[0]= (dialog.open() == Window.OK);
668 			}
669 		});
670 	}
671 
672 	/**
673 	 * Displays the given preference page
674 	 * @param pageId the fully qualified id of the preference page, e.g. <code>org.eclipse.jdt.debug.ui.preferences.VMPreferencePage</code>
675 	 *
676 	 * @since 3.3
677 	 */
showPreferencePage(String pageId)678 	public static void showPreferencePage(String pageId) {
679 		PreferencesUtil.createPreferenceDialogOn(getShell(), pageId, new String[] { pageId }, null).open();
680 	}
681 
682 	/**
683 	 * Returns the text tools used by this plug-in
684 	 *
685 	 * @return
686 	 */
getJavaTextTools()687 	public JavaTextTools getJavaTextTools() {
688 		if (fTextTools == null) {
689 			fTextTools = new JavaTextTools(PreferenceConstants.getPreferenceStore());
690 		}
691 		return fTextTools;
692 	}
693 }
694 
695