/******************************************************************************* * Copyright (c) 2000, 2015 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 * QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640) * Valentin Ciocoi - Bug 414994 Guard against out of bounds exception when handling escaped characters in DefaultLabelProvider *******************************************************************************/ package org.eclipse.debug.internal.ui; import java.util.HashMap; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.debug.core.DebugException; 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.ILaunchManager; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IDisconnect; import org.eclipse.debug.core.model.IExpression; import org.eclipse.debug.core.model.ILineBreakpoint; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IRegister; import org.eclipse.debug.core.model.IRegisterGroup; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.ITerminate; import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.core.model.IWatchExpression; import org.eclipse.debug.core.model.IWatchpoint; import org.eclipse.debug.internal.core.IInternalDebugCoreConstants; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchShortcutExtension; import org.eclipse.debug.internal.ui.views.variables.IndexedVariablePartition; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IBaseLabelProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.model.IWorkbenchAdapter; import com.ibm.icu.text.MessageFormat; public class DefaultLabelProvider implements ILabelProvider { /** * Maps image descriptors to images. */ private Map fImages = new HashMap<>(); /** * @see ILabelProvider#getImage(Object) */ @Override public Image getImage(Object element) { String key= getImageKey(element); if (key == null && element instanceof ILaunch) { return null; } if (key == null && element instanceof IAdaptable) { IWorkbenchAdapter de= ((IAdaptable) element).getAdapter(IWorkbenchAdapter.class); if (de != null) { ImageDescriptor descriptor= de.getImageDescriptor(element); if( descriptor != null) { return getImage(descriptor); } } return null; } if(element instanceof LaunchShortcutExtension) { return getImage(((LaunchShortcutExtension)element).getImageDescriptor()); } return DebugPluginImages.getImage(key); } /** * Returns an image created from the given image descriptor or null. * Caches and reuses images. * * @param descriptor image descriptor * @return image or null */ private Image getImage(ImageDescriptor descriptor) { Image image = fImages.get(descriptor); if (image != null) { return image; } image = descriptor.createImage(); if (image != null) { fImages.put(descriptor, image); } return image; } /** * Returns the key (String) of the default image * appropriate for the given element or null * if no default image is defined. */ public String getImageKey(Object element) { if (element instanceof IDebugElement) { // Group elements into debug elements and non-debug elements // to reduce the number of instanceof checks performed if (element instanceof IRegister) { return IDebugUIConstants.IMG_OBJS_REGISTER; } else if (element instanceof IRegisterGroup) { return IDebugUIConstants.IMG_OBJS_REGISTER_GROUP; } else if (element instanceof IVariable || element instanceof IValue) { if (element instanceof IndexedVariablePartition) { return IInternalDebugUIConstants.IMG_OBJS_ARRAY_PARTITION; } return IDebugUIConstants.IMG_OBJS_VARIABLE; } else if (element instanceof IStackFrame) { if (((IStackFrame)element).getThread().isSuspended()) { return IDebugUIConstants.IMG_OBJS_STACKFRAME; } return IDebugUIConstants.IMG_OBJS_STACKFRAME_RUNNING; } else if (element instanceof IThread) { IThread thread = (IThread)element; if (thread.isSuspended()) { return IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; } else if (thread.isTerminated()) { return IDebugUIConstants.IMG_OBJS_THREAD_TERMINATED; } else { return IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; } } else if (element instanceof IDebugTarget) { IDebugTarget target= (IDebugTarget) element; if (target.isTerminated() || target.isDisconnected()) { return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_TERMINATED; } else if (target.isSuspended()) { return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_SUSPENDED; } else { return IDebugUIConstants.IMG_OBJS_DEBUG_TARGET; } } else if (element instanceof IExpression) { return IDebugUIConstants.IMG_OBJS_EXPRESSION; } } else { if (element instanceof IMarker) { return getMarkerImageKey((IMarker)element); } else if (element instanceof IBreakpoint) { return getBreakpointImageKey((IBreakpoint)element); } else if (element instanceof IProcess) { if (((IProcess) element).isTerminated()) { return IDebugUIConstants.IMG_OBJS_OS_PROCESS_TERMINATED; } return IDebugUIConstants.IMG_OBJS_OS_PROCESS; } else if (element instanceof ILaunch) { // determine the image from the launch config type ILaunch launch= (ILaunch)element; ILaunchConfiguration configuration = launch.getLaunchConfiguration(); if (configuration != null) { try { return configuration.getType().getIdentifier(); } catch (CoreException e) { DebugUIPlugin.log(e); return null; } } // if no config, use the old "mode" way if (launch.getLaunchMode().equals(ILaunchManager.DEBUG_MODE)) { return IDebugUIConstants.IMG_OBJS_LAUNCH_DEBUG; } else if (launch.isTerminated()) { return IDebugUIConstants.IMG_OBJS_LAUNCH_RUN_TERMINATED; } else { return IDebugUIConstants.IMG_OBJS_LAUNCH_RUN; } } else if (element instanceof ILaunchConfigurationType) { return ((ILaunchConfigurationType)element).getIdentifier(); } else if (element instanceof ILaunchConfiguration) { try { return ((ILaunchConfiguration)element).getType().getIdentifier(); } catch (CoreException e) { DebugUIPlugin.log(e); return null; } } } return null; } /** * @see ILabelProvider#getText(Object) */ @Override public String getText(Object element) { StringBuffer label= new StringBuffer(); try { // Group elements into debug elements and non-debug elements // to reduce the number of instanceof checks performed if (element instanceof IDebugElement) { if (element instanceof IStackFrame) { label.append(((IStackFrame)element).getName()); } else if (element instanceof IndexedVariablePartition) { label.append(((IndexedVariablePartition)element).getName()); } else if (element instanceof IVariable) { label.append(getVariableText((IVariable)element)); } else if (element instanceof IThread) { label.append(((IThread)element).getName()); } else if (element instanceof IDebugTarget) { label.append((((IDebugTarget)element).getName())); } else if (element instanceof IExpression) { label.append(getExpressionText((IExpression)element)); } else if (element instanceof IRegisterGroup) { label.append(getRegisterGroupText((IRegisterGroup)element)); } else if (element instanceof IValue) { label.append(((IValue)element).getValueString()); } } else { if (element instanceof IMarker) { label.append(getMarkerText((IMarker) element)); } else if (element instanceof IBreakpoint) { label.append(getBreakpointText((IBreakpoint)element)); } else if (element instanceof IProcess) { label.append(((IProcess) element).getLabel()); } else if (element instanceof ILaunch) { label.append(getLaunchText((ILaunch) element)); } else if (element instanceof ILaunchConfiguration) { label.append(((ILaunchConfiguration)element).getName()); } else if (element instanceof ILaunchConfigurationType) { label.append(((ILaunchConfigurationType)element).getName()); } else if(element instanceof ILaunchDelegate) { ILaunchDelegate delegate = (ILaunchDelegate) element; String name = delegate.getName(); if(name == null) { name = delegate.getContributorName(); } label.append(name); } else if(element instanceof LaunchShortcutExtension) { label.append(((LaunchShortcutExtension)element).getLabel()); } else if (element instanceof String) { label.append(element); } else { label.append(getAdapterLabel(element)); } } if (element instanceof ITerminate) { if (((ITerminate) element).isTerminated()) { String terminatedMessage= null; if (element instanceof IProcess) { IProcess process = (IProcess)element; int exit = process.getExitValue(); terminatedMessage = MessageFormat.format(DebugUIMessages.DefaultLabelProvider_16, new Object[] { Integer.valueOf(exit).toString() }); } else { terminatedMessage= DebugUIMessages.DefaultLabelProvider_1; } label.insert(0, terminatedMessage); } } else if (element instanceof IDisconnect) { if (((IDisconnect) element).isDisconnected()) { label.insert(0, DebugUIMessages.DefaultLabelProvider__disconnected__1); } } } catch (DebugException e) { DebugUIPlugin.log(e); label.append(DebugUIMessages.DefaultLabelProvider__unknown__1); } return label.toString(); } /** * Returns default label for a breakpoint. * * @param breakpoint * @return default label for a breakpoint */ private String getBreakpointText(IBreakpoint breakpoint) { IResource resource = breakpoint.getMarker().getResource(); StringBuffer label = new StringBuffer(); if (resource != null) { label.append(resource.getName()); } if (breakpoint instanceof ILineBreakpoint) { try { int lineNumber = ((ILineBreakpoint)breakpoint).getLineNumber(); label.append(MessageFormat.format(DebugUIMessages.DefaultLabelProvider_17, new Object[] { Integer.toString(lineNumber) })); } catch (CoreException e) { } } return label.toString(); } public String getAdapterLabel(Object object) { if (object instanceof IAdaptable) { IWorkbenchAdapter de= ((IAdaptable) object).getAdapter(IWorkbenchAdapter.class); if (de != null) { return de.getLabel(object); } } return DebugUIMessages.DefaultLabelProvider__unknown__1; } /** * Used to render launch history items in the re-launch drop downs */ protected String getLaunchText(ILaunch launch) { if (launch.getLaunchConfiguration() == null || (!launch.getLaunchConfiguration().exists() && !launch.getLaunchConfiguration().isWorkingCopy())) { return DebugUIMessages.DefaultLabelProvider__unknown__1; } // new launch configuration ILaunchConfiguration config = launch.getLaunchConfiguration(); StringBuffer buff= new StringBuffer(config.getName()); buff.append(" ["); //$NON-NLS-1$ try { buff.append(config.getType().getName()); } catch (CoreException e) { DebugUIPlugin.log(e); } buff.append("]"); //$NON-NLS-1$ return buff.toString(); } protected String getExpressionText(IExpression expression) { if (expression instanceof IWatchExpression) { return getWatchExpressionText((IWatchExpression) expression); } StringBuffer buffer= new StringBuffer(expression.getExpressionText()); String valueString= null; IValue value= expression.getValue(); if (value != null) { try { valueString= value.getValueString(); } catch (DebugException de) { DebugUIPlugin.log(de); } } if (valueString != null && valueString.length() > 0) { buffer.append("= "); //$NON-NLS-1$ buffer.append(valueString); } return buffer.toString(); } /** * @param expression * @return */ protected String getWatchExpressionText(IWatchExpression expression) { StringBuffer result= new StringBuffer(); String snippet = expression.getExpressionText().trim(); StringBuffer snippetBuffer = new StringBuffer(); if (snippet.length() > 30){ snippetBuffer.append(snippet.substring(0, 15)); snippetBuffer.append(DebugUIMessages.DefaultLabelProvider_0); snippetBuffer.append(snippet.substring(snippet.length() - 15)); } else { snippetBuffer.append(snippet); } snippet = snippetBuffer.toString().replaceAll("[\n\r\t]+", " "); //$NON-NLS-1$//$NON-NLS-2$ result.append('"'); result.append(snippet); result.append('"'); if (expression.isPending()) { result.append(DebugUIMessages.DefaultLabelProvider_12); } else if (expression.hasErrors()) { result.append(DebugUIMessages.DefaultLabelProvider_13); } else { IValue value= expression.getValue(); if (value != null) { String valueString= DebugUIPlugin.getModelPresentation().getText(value); if (valueString.length() > 0) { result.append(" = ").append(valueString); //$NON-NLS-1$ } } } if (!expression.isEnabled()) { result.append(DebugUIMessages.DefaultLabelProvider_15); } return result.toString(); } protected String getVariableText(IVariable variable) { StringBuffer buffer= new StringBuffer(); try { IValue value = variable.getValue(); buffer.append(variable.getName()); buffer.append(" = "); //$NON-NLS-1$ buffer.append(value.getValueString()); } catch (DebugException de) { DebugUIPlugin.log(de); } return buffer.toString(); } protected String getRegisterGroupText(IRegisterGroup registerGroup) { StringBuffer buffer= new StringBuffer(); try { buffer.append(registerGroup.getName()); } catch (DebugException de) { DebugUIPlugin.log(de); } return buffer.toString(); } protected String getMarkerText(IMarker marker) { try { if (marker.exists() && marker.isSubtypeOf(IBreakpoint.BREAKPOINT_MARKER)) { return DebugUIMessages.DefaultLabelProvider_Breakpoint_1; } } catch (CoreException e) { DebugUIPlugin.log(e); } return IInternalDebugCoreConstants.EMPTY_STRING; } protected String getMarkerImageKey(IMarker marker) { try { IBreakpoint breakpoint= DebugPlugin.getDefault().getBreakpointManager().getBreakpoint(marker); if (breakpoint != null && marker.exists()) { if (breakpoint.isEnabled()) { return IDebugUIConstants.IMG_OBJS_BREAKPOINT; } return IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED; } } catch (CoreException e) { } return null; } protected String getBreakpointImageKey(IBreakpoint breakpoint) { if (breakpoint != null && breakpoint.getMarker().exists()) { try { boolean enabled = breakpoint.isEnabled(); if (breakpoint instanceof IWatchpoint) { IWatchpoint watchpoint = (IWatchpoint) breakpoint; if (watchpoint.isAccess()) { if (watchpoint.isModification()) { //access and modification if (enabled) { return IDebugUIConstants.IMG_OBJS_WATCHPOINT; } return IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED; } if (enabled) { return IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT; } return IDebugUIConstants.IMG_OBJS_ACCESS_WATCHPOINT_DISABLED; } else if (watchpoint.isModification()) { if (enabled) { return IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT; } return IDebugUIConstants.IMG_OBJS_MODIFICATION_WATCHPOINT_DISABLED; } else { //neither access nor modification return IDebugUIConstants.IMG_OBJS_WATCHPOINT_DISABLED; } } if (enabled) { return IDebugUIConstants.IMG_OBJS_BREAKPOINT; } return IDebugUIConstants.IMG_OBJS_BREAKPOINT_DISABLED; } catch (CoreException e) { } } return null; } /** * @see IBaseLabelProvider#addListener(ILabelProviderListener) */ @Override public void addListener(ILabelProviderListener listener) { } /** * @see IBaseLabelProvider#dispose() */ @Override public void dispose() { for (Image image : fImages.values()) { image.dispose(); } fImages.clear(); } /** * @see IBaseLabelProvider#isLabelProperty(Object, String) */ @Override public boolean isLabelProperty(Object element, String property) { return false; } /** * @see IBaseLabelProvider#removeListener(ILabelProviderListener) */ @Override public void removeListener(ILabelProviderListener listener) { } /** * Returns the given string with special chars in escaped sequences. * * @param label * @return the given string with special chars in escaped sequences * @since 3.3 */ public static String escapeSpecialChars(String string) { if (string == null) { return null; } StringBuffer escaped = new StringBuffer(); for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); switch (c) { case '\b': escaped.append("\\b"); //$NON-NLS-1$ break; case '\f': escaped.append("\\f"); //$NON-NLS-1$ break; case '\n': escaped.append("\\n"); //$NON-NLS-1$ break; case '\r': escaped.append("\\r"); //$NON-NLS-1$ break; case '\t': escaped.append("\\t"); //$NON-NLS-1$ break; case '\\': escaped.append("\\\\"); //$NON-NLS-1$ break; default: escaped.append(c); break; } } return escaped.toString(); } /** * Returns the string with escaped sequences replaced with single chars. * * @param string * @return the string with escaped sequences replaced with single chars * @since 3.3 */ public static String encodeEsacpedChars(String string) { if (string == null) { return null; } StringBuffer encoded = new StringBuffer(); if (string.length() == 1) { return string; } for (int i = 0; i < string.length(); i++) { char c = string.charAt(i); if (c == '\\' && (i + 1 < string.length())) { switch (string.charAt(i+1)) { case 'b': c= '\b'; i++; break; case 'f': c= '\f'; i++; break; case 'n': c= '\n'; i++; break; case 'r': c= '\r'; i++; break; case 't': c= '\t'; i++; break; case '\'': c= '\''; i++; break; case '\\': c= '\\'; i++; break; default : break; } } encoded.append(c); } return encoded.toString(); } }