blob: 88aa66359803edd810b2c5f104b5c1b9f87fb7b3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.debug.ui;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.ISaveContext;
import org.eclipse.core.resources.ISaveParticipant;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.core.runtime.IAdapterManager;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.ILaunchConfigurationTab;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaHotCodeReplaceListener;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaThreadGroup;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
import org.eclipse.jdt.internal.debug.ui.breakpoints.ExceptionInspector;
import org.eclipse.jdt.internal.debug.ui.breakpoints.JavaBreakpointTypeAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.classpath.ClasspathEntryAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaContendedMonitor;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwnedMonitor;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaOwningThread;
import org.eclipse.jdt.internal.debug.ui.monitors.JavaWaitingThread;
import org.eclipse.jdt.internal.debug.ui.monitors.MonitorsAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.snippeteditor.SnippetFileDocumentProvider;
import org.eclipse.jdt.internal.debug.ui.sourcelookup.JavaDebugShowInAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.threadgroups.TargetAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.threadgroups.ThreadGroupAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.variables.ColumnPresentationAdapterFactory;
import org.eclipse.jdt.internal.debug.ui.variables.JavaDebugElementAdapterFactory;
import org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry;
import org.eclipse.jdt.launching.sourcelookup.IJavaSourceLocation;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
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.resource.ImageRegistry;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.custom.BusyIndicator;
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.PlatformUI;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;
/**
* Plug-in class for the org.eclipse.jdt.debug.ui plug-in.
*/
public class JDIDebugUIPlugin extends AbstractUIPlugin {
/**
* Unique identifier constant (value <code>"org.eclipse.jdt.debug.ui"</code>)
* for the JDI Debug plug-in.
*/
private static final String PI_JDI_DEBUG = "org.eclipse.jdt.debug.ui"; //$NON-NLS-1$
/**
* Id for inspect command.
*
* @since 3.3
*/
public static final String COMMAND_INSPECT = "org.eclipse.jdt.debug.ui.commands.Inspect"; //$NON-NLS-1$
/**
* Java Debug UI plug-in instance
*/
private static JDIDebugUIPlugin fgPlugin;
private IDocumentProvider fSnippetDocumentProvider;
private ImageDescriptorRegistry fImageDescriptorRegistry;
private ActionFilterAdapterFactory fActionFilterAdapterFactory;
private JavaSourceLocationWorkbenchAdapterFactory fSourceLocationAdapterFactory;
private JavaBreakpointWorkbenchAdapterFactory fBreakpointAdapterFactory;
private IDebugModelPresentation fUtilPresentation;
/**
* Java Debug UI listeners
*/
private IJavaHotCodeReplaceListener fHCRListener;
// Map of VMInstallTypeIDs to IConfigurationElements
protected Map<String, IConfigurationElement> fVmInstallTypePageMap;
/**
* Whether this plugin is in the process of shutting
* down.
*/
private boolean fShuttingDown= false;
/**
* Singleton text tools for debug plug-in.
*/
private JavaTextTools fTextTools = null;
/**
* @see Plugin()
*/
public JDIDebugUIPlugin() {
super();
setDefault(this);
}
/**
* Sets the Java Debug UI plug-in instance
*
* @param plugin the plugin instance
*/
private static void setDefault(JDIDebugUIPlugin plugin) {
fgPlugin = plugin;
}
/**
* Returns the Java Debug UI plug-in instance
*
* @return the Java Debug UI plug-in instance
*/
public static JDIDebugUIPlugin getDefault() {
return fgPlugin;
}
/**
* Convenience method which returns the unique identifier of this plugin.
*/
public static String getUniqueIdentifier() {
return PI_JDI_DEBUG;
}
/**
* 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 and throwable
*
* @param message the error message to log
* @param e
* the exception to be logged
*/
public static void log(String message, Throwable e) {
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, e));
}
/**
* 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(), IJavaDebugUIConstants.INTERNAL_ERROR, "Internal Error", e)); //$NON-NLS-1$
}
/**
* Returns the active workbench window
*
* @return the active workbench window
*/
public static IWorkbenchWindow getActiveWorkbenchWindow() {
return PlatformUI.getWorkbench().getActiveWorkbenchWindow();
}
public static IWorkbenchPage getActivePage() {
IWorkbenchWindow w = getActiveWorkbenchWindow();
if (w != null) {
return w.getActivePage();
}
return null;
}
/**
* 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;
}
/* (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#createImageRegistry()
*/
@Override
protected ImageRegistry createImageRegistry() {
return JavaDebugImages.getImageRegistry();
}
public IDocumentProvider getSnippetDocumentProvider() {
if (fSnippetDocumentProvider == null) {
fSnippetDocumentProvider= new SnippetFileDocumentProvider();
}
return fSnippetDocumentProvider;
}
public static void statusDialog(IStatus status) {
switch (status.getSeverity()) {
case IStatus.ERROR:
statusDialog(DebugUIMessages.JDIDebugUIPlugin_Error_1, status);
break;
case IStatus.WARNING:
statusDialog(DebugUIMessages.JDIDebugUIPlugin_0, status);
break;
case IStatus.INFO:
statusDialog(DebugUIMessages.JDIDebugUIPlugin_4, status);
break;
}
}
public static void statusDialog(String title, IStatus status) {
Shell shell = getActiveWorkbenchShell();
if (shell != null) {
switch (status.getSeverity()) {
case IStatus.ERROR:
ErrorDialog.openError(shell, title, null, status);
break;
case IStatus.WARNING:
MessageDialog.openWarning(shell, title, status.getMessage());
break;
case IStatus.INFO:
MessageDialog.openInformation(shell, title, status.getMessage());
break;
}
}
}
/**
* Creates a new internal error status with the specified message and throwable, then displays
* it in a status dialog.
*
* @param message error message
* @param t throwable cause or <code>null</code>
*/
public static void errorDialog(String message, Throwable t) {
IStatus status= new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, message, t);
statusDialog(status);
}
/**
* Opens an error dialog with the given title and message.
*/
public static void errorDialog(Shell shell, String title, String message, Throwable t) {
IStatus status;
if (t instanceof CoreException) {
status= ((CoreException)t).getStatus();
// if the 'message' resource string and the IStatus' message are the same,
// don't show both in the dialog
if (status != null && message.equals(status.getMessage())) {
message= null;
}
} else {
status= new Status(IStatus.ERROR, getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, "Error within Debug UI: ", t); //$NON-NLS-1$
log(status);
}
ErrorDialog.openError(shell, title, message, status);
}
/**
* Creates an extension. If the extension plugin has not
* been loaded a busy cursor will be activated during the duration of
* the load.
*
* @param element the config element defining the extension
* @param classAttribute the name of the attribute carrying the class
* @return the extension object
*/
public static Object createExtension(final IConfigurationElement element, final String classAttribute) throws CoreException {
// If plugin has been loaded create extension.
// Otherwise, show busy cursor then create extension.
Bundle bundle = Platform.getBundle(element.getContributor().getName());
if (bundle.getState() == Bundle.ACTIVE) {
return element.createExecutableExtension(classAttribute);
}
final Object [] ret = new Object[1];
final CoreException [] exc = new CoreException[1];
BusyIndicator.showWhile(null, new Runnable() {
@Override
public void run() {
try {
ret[0] = element.createExecutableExtension(classAttribute);
} catch (CoreException e) {
exc[0] = e;
}
}
});
if (exc[0] != null) {
throw exc[0];
}
return ret[0];
}
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/
@Override
public void start(BundleContext context) throws Exception {
super.start(context);
IAdapterManager manager= Platform.getAdapterManager();
fActionFilterAdapterFactory= new ActionFilterAdapterFactory();
manager.registerAdapters(fActionFilterAdapterFactory, IMember.class);
manager.registerAdapters(fActionFilterAdapterFactory, IJavaVariable.class);
manager.registerAdapters(fActionFilterAdapterFactory, IJavaStackFrame.class);
manager.registerAdapters(fActionFilterAdapterFactory, IJavaThread.class);
manager.registerAdapters(fActionFilterAdapterFactory, JavaInspectExpression.class);
fSourceLocationAdapterFactory = new JavaSourceLocationWorkbenchAdapterFactory();
manager.registerAdapters(fSourceLocationAdapterFactory, IJavaSourceLocation.class);
fBreakpointAdapterFactory= new JavaBreakpointWorkbenchAdapterFactory();
manager.registerAdapters(fBreakpointAdapterFactory, IJavaBreakpoint.class);
IAdapterFactory typeFactory = new JavaBreakpointTypeAdapterFactory();
manager.registerAdapters(typeFactory, IJavaBreakpoint.class);
IAdapterFactory monitorFactory = new MonitorsAdapterFactory();
manager.registerAdapters(monitorFactory, IJavaThread.class);
manager.registerAdapters(monitorFactory, JavaContendedMonitor.class);
manager.registerAdapters(monitorFactory, JavaOwnedMonitor.class);
manager.registerAdapters(monitorFactory, JavaOwningThread.class);
manager.registerAdapters(monitorFactory, JavaWaitingThread.class);
manager.registerAdapters(monitorFactory, IJavaStackFrame.class);
IAdapterFactory targetFactory = new TargetAdapterFactory();
manager.registerAdapters(targetFactory, IJavaDebugTarget.class);
IAdapterFactory groupFactory = new ThreadGroupAdapterFactory();
manager.registerAdapters(groupFactory, IJavaThreadGroup.class);
IAdapterFactory showInFactory = new JavaDebugShowInAdapterFactory();
manager.registerAdapters(showInFactory, IJavaStackFrame.class);
IAdapterFactory columnFactory = new ColumnPresentationAdapterFactory();
manager.registerAdapters(columnFactory, IJavaVariable.class);
manager.registerAdapters(columnFactory, IJavaStackFrame.class);
IAdapterFactory entryFactory = new ClasspathEntryAdapterFactory();
manager.registerAdapters(entryFactory, DefaultProjectClasspathEntry.class);
IAdapterFactory variableFactory = new JavaDebugElementAdapterFactory();
manager.registerAdapters(variableFactory, IJavaVariable.class);
manager.registerAdapters(variableFactory, IJavaValue.class);
manager.registerAdapters(variableFactory, JavaInspectExpression.class);
fHCRListener= new JavaHotCodeReplaceListener();
JDIDebugModel.addHotCodeReplaceListener(fHCRListener);
// initialize exception inspector handler
new ExceptionInspector();
ResourcesPlugin.getWorkspace().addSaveParticipant(getUniqueIdentifier(), new ISaveParticipant() {
@Override
public void doneSaving(ISaveContext sc) {}
@Override
public void prepareToSave(ISaveContext sc) throws CoreException {}
@Override
public void rollback(ISaveContext sc) {}
@Override
public void saving(ISaveContext sc) throws CoreException {
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(getUniqueIdentifier());
if(prefs != null) {
try {
prefs.flush();
}
catch (BackingStoreException e) {
log(e);
}
}
}
});
JavaDebugOptionsManager.getDefault().startup();
}
/* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/
@Override
public void stop(BundleContext context) throws Exception {
try {
setShuttingDown(true);
JDIDebugModel.removeHotCodeReplaceListener(fHCRListener);
JavaDebugOptionsManager.getDefault().shutdown();
if (fImageDescriptorRegistry != null) {
fImageDescriptorRegistry.dispose();
}
IAdapterManager manager= Platform.getAdapterManager();
manager.unregisterAdapters(fActionFilterAdapterFactory);
manager.unregisterAdapters(fSourceLocationAdapterFactory);
manager.unregisterAdapters(fBreakpointAdapterFactory);
if (fUtilPresentation != null) {
fUtilPresentation.dispose();
}
if (fTextTools != null) {
fTextTools.dispose();
}
ResourcesPlugin.getWorkspace().removeSaveParticipant(getUniqueIdentifier());
} 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
*/
protected boolean isShuttingDown() {
return fShuttingDown;
}
/**
* Sets whether this plug-in is in the process of
* being shutdown.
*
* @param value whether this plug-in is in the process of
* being shutdown
*/
private void setShuttingDown(boolean value) {
fShuttingDown = value;
}
/**
* Returns the image descriptor registry used for this plugin.
*/
public static ImageDescriptorRegistry getImageDescriptorRegistry() {
if (getDefault().fImageDescriptorRegistry == null) {
getDefault().fImageDescriptorRegistry = new ImageDescriptorRegistry();
}
return getDefault().fImageDescriptorRegistry;
}
/**
* 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() {
Display display;
display= Display.getCurrent();
if (display == null) {
display= Display.getDefault();
}
return display;
}
/**
* Returns the currently active workbench window shell or <code>null</code>
* if none.
*
* @return the currently active workbench window shell or <code>null</code>
*/
public static Shell getShell() {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (window == null) {
IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
if (windows.length > 0) {
return windows[0].getShell();
}
}
else {
return window.getShell();
}
return null;
}
/**
* Utility method to create and return a selection dialog that allows
* selection of a specific Java package. Empty packages are not returned.
* If Java Projects are provided, only packages found within those projects
* are included. If no Java projects are provided, all Java projects in the
* workspace are considered.
*/
public static ElementListSelectionDialog createAllPackagesDialog(Shell shell, IJavaProject[] originals, final boolean includeDefaultPackage) throws JavaModelException{
final List<IPackageFragment> packageList = new ArrayList<>();
if (originals == null) {
IWorkspaceRoot wsroot= ResourcesPlugin.getWorkspace().getRoot();
IJavaModel model= JavaCore.create(wsroot);
originals= model.getJavaProjects();
}
final IJavaProject[] projects= originals;
final JavaModelException[] exception= new JavaModelException[1];
final boolean[] monitorCanceled = new boolean[] {false};
IRunnableWithProgress r= new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) {
try {
Set<String> packageNameSet= new HashSet<>();
monitor.beginTask(DebugUIMessages.JDIDebugUIPlugin_Searching_1, projects.length);
for (int i = 0; i < projects.length; i++) {
IPackageFragment[] pkgs= projects[i].getPackageFragments();
for (int j = 0; j < pkgs.length; j++) {
if (monitor.isCanceled()) {
monitorCanceled[0] = true;
return;
}
IPackageFragment pkg = pkgs[j];
if (!pkg.hasChildren() && (pkg.getNonJavaResources().length > 0)) {
continue;
}
String pkgName= pkg.getElementName();
if (!includeDefaultPackage && pkgName.length() == 0) {
continue;
}
if (packageNameSet.add(pkgName)) {
packageList.add(pkg);
}
}
monitor.worked(1);
}
monitor.done();
} catch (JavaModelException jme) {
exception[0]= jme;
}
}
};
try {
PlatformUI.getWorkbench().getProgressService().busyCursorWhile(r);
} catch (InvocationTargetException e) {
JDIDebugUIPlugin.log(e);
} catch (InterruptedException e) {
JDIDebugUIPlugin.log(e);
}
if (exception[0] != null) {
throw exception[0];
}
if (monitorCanceled[0]) {
return null;
}
int flags= JavaElementLabelProvider.SHOW_DEFAULT;
PackageSelectionDialog dialog= new PackageSelectionDialog(shell, new JavaElementLabelProvider(flags));
dialog.setIgnoreCase(false);
dialog.setElements(packageList.toArray()); // XXX inefficient
return dialog;
}
/**
* Return an object that implements <code>ILaunchConfigurationTab</code> for the
* specified vm install type ID.
*/
public ILaunchConfigurationTab getVMInstallTypePage(String vmInstallTypeID) {
if (fVmInstallTypePageMap == null) {
initializeVMInstallTypePageMap();
}
IConfigurationElement configElement = fVmInstallTypePageMap.get(vmInstallTypeID);
ILaunchConfigurationTab tab = null;
if (configElement != null) {
try {
tab = (ILaunchConfigurationTab) configElement.createExecutableExtension("class"); //$NON-NLS-1$
} catch(CoreException ce) {
log(new Status(IStatus.ERROR, getUniqueIdentifier(), IJavaDebugUIConstants.INTERNAL_ERROR, "An error occurred retrieving a VMInstallType page.", ce)); //$NON-NLS-1$
}
}
return tab;
}
protected void initializeVMInstallTypePageMap() {
fVmInstallTypePageMap = new HashMap<>(10);
IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(getUniqueIdentifier(), IJavaDebugUIConstants.EXTENSION_POINT_VM_INSTALL_TYPE_PAGE);
IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
for (int i = 0; i < infos.length; i++) {
String id = infos[i].getAttribute("vmInstallTypeID"); //$NON-NLS-1$
fVmInstallTypePageMap.put(id, infos[i]);
}
}
/**
* Returns a shared utility Java debug model presentation. Clients should not
* dispose the presentation.
*
* @return a Java debug model presentation
*/
public IDebugModelPresentation getModelPresentation() {
if (fUtilPresentation == null) {
fUtilPresentation = DebugUITools.newDebugModelPresentation(JDIDebugModel.getPluginIdentifier());
}
return fUtilPresentation;
}
/**
* Displays the given preference page.
*
* @param id pref page id
* @param page pref page
* @deprecated use <code>JDIDebugUIPlugin#showPreferencePage(String pageId)</code>, which uses the <code>PreferenceUtils</code> framework for opening pages.
*/
@Deprecated
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(JDIDebugUIPlugin.getActiveWorkbenchShell(), manager);
final boolean [] result = new boolean[] { false };
BusyIndicator.showWhile(JDIDebugUIPlugin.getStandardDisplay(), new Runnable() {
@Override
public void run() {
dialog.create();
dialog.setMessage(targetNode.getLabelText());
result[0]= (dialog.open() == Window.OK);
}
});
}
/**
* Displays the given preference page
* @param pageId the fully qualified id of the preference page, e.g. <code>org.eclipse.jdt.debug.ui.preferences.VMPreferencePage</code>
*
* @since 3.3
*/
public static void showPreferencePage(String pageId) {
PreferencesUtil.createPreferenceDialogOn(getShell(), pageId, new String[] { pageId }, null).open();
}
/**
* Returns the text tools used by this plug-in
*
* @return
*/
public JavaTextTools getJavaTextTools() {
if (fTextTools == null) {
fTextTools = new JavaTextTools(PreferenceConstants.getPreferenceStore());
}
return fTextTools;
}
}