/******************************************************************************* * Copyright (c) 2007, 2016 Wind River Systems, Inc. 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.internal.debug.ui.model; import java.math.BigInteger; import java.net.URI; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.URIUtil; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IStorage; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.ILineBreakpoint; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.IValueDetailListener; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.swt.graphics.Image; import org.eclipse.tcf.internal.debug.model.TCFBreakpointsModel; import org.eclipse.tcf.internal.debug.model.TCFLaunch; import org.eclipse.tcf.internal.debug.model.TCFSourceRef; import org.eclipse.tcf.internal.debug.ui.Activator; import org.eclipse.tcf.internal.debug.ui.ImageCache; import org.eclipse.tcf.protocol.JSON; import org.eclipse.tcf.services.IBreakpoints; import org.eclipse.tcf.services.ILineNumbers; import org.eclipse.tcf.util.TCFDataCache; import org.eclipse.tcf.util.TCFTask; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorRegistry; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.ui.part.FileEditorInput; public class TCFModelPresentation implements IDebugModelPresentation { public final static String DISPLAY_FULL_PATHS = "DISPLAY_FULL_PATHS"; //$NON-NLS-1$ private static final String[] attr_names = { TCFBreakpointsModel.ATTR_LINE, "line", TCFBreakpointsModel.ATTR_ADDRESS, "address", TCFBreakpointsModel.ATTR_FUNCTION, "location", TCFBreakpointsModel.ATTR_EXPRESSION, "expression", TCFBreakpointsModel.ATTR_CONDITION, "condition", TCFBreakpointsModel.ATTR_EVENT_TYPE, "event type", TCFBreakpointsModel.ATTR_EVENT_ARGS, "event args", TCFBreakpointsModel.ATTR_CONTEXTNAMES, "scope (names)", TCFBreakpointsModel.ATTR_CONTEXTIDS, "scope (IDs)", TCFBreakpointsModel.ATTR_EXE_PATHS, "scope (modules)", TCFBreakpointsModel.ATTR_STOP_GROUP, "stop group", }; private final Collection<ILabelProviderListener> listeners = new HashSet<ILabelProviderListener>(); private HashMap<String,Object> attrs = new HashMap<String,Object>(); private static final TCFModelPresentation default_instance = new TCFModelPresentation(); public static TCFModelPresentation getDefault() { return default_instance; } public void addListener(ILabelProviderListener listener) { listeners.add(listener); } public void removeListener(ILabelProviderListener listener) { listeners.remove(listener); } public void dispose() { } public void computeDetail(IValue value, IValueDetailListener listener) { } public Image getImage(Object element) { ImageDescriptor descriptor = null; if (element instanceof IBreakpoint) { final IBreakpoint breakpoint = (IBreakpoint)element; descriptor = ImageCache.getImageDescriptor(ImageCache.IMG_BREAKPOINT_DISABLED); try { if (breakpoint.isEnabled()) { descriptor = new TCFTask<ImageDescriptor>() { public void run() { boolean installed = false; boolean warning = false; boolean error = false; boolean moved = false; ImageDescriptor d = ImageCache.getImageDescriptor(ImageCache.IMG_BREAKPOINT_ENABLED); Map<TCFLaunch,Map<String,Object>> status = Activator.getAnnotationManager().getBreakpointStatus(breakpoint); for (TCFLaunch launch : status.keySet()) { Map<String,Object> map = status.get(launch); if (map == null) continue; if ((String)map.get(IBreakpoints.STATUS_ERROR) != null) error = true; Object planted = map.get(IBreakpoints.STATUS_INSTANCES); if (planted == null) continue; @SuppressWarnings("unchecked") Collection<Map<String,Object>> list = (Collection<Map<String,Object>>)planted; for (Map<String,Object> m : list) { if (m.get(IBreakpoints.INSTANCE_CONDITION_ERROR) != null) error = true; if (m.get(IBreakpoints.INSTANCE_ERROR) == null) { installed = true; if (!moved) { TCFNodeExecContext ctx = null; String ctx_id = (String)m.get(IBreakpoints.INSTANCE_CONTEXT); BigInteger addr = JSON.toBigInteger((Number)m.get(IBreakpoints.INSTANCE_ADDRESS)); int line = breakpoint.getMarker().getAttribute(TCFBreakpointsModel.ATTR_LINE, 0); if (ctx_id != null && addr != null && line > 0) { TCFModel model = TCFModelManager.getModelManager().getModel(launch); if (model != null) { if (!model.createNode(ctx_id, this)) return; TCFDataCache<TCFNodeExecContext> mem = model.searchMemoryContext(model.getNode(ctx_id)); if (mem != null) { if (!mem.validate(this)) return; ctx = mem.getData(); } } } if (ctx != null) { ILineNumbers.CodeArea area = null; TCFDataCache<TCFSourceRef> line_cache = ctx.getLineInfo(addr); if (line_cache != null) { if (!line_cache.validate(this)) return; TCFSourceRef line_data = line_cache.getData(); if (line_data != null && line_data.area != null) area = line_data.area; } if (area != null && area.start_line != line) moved = true; } } } else { warning = true; } } } if (moved) d = ImageCache.addOverlay(d, ImageCache.IMG_BREAKPOINT_MOVED, 0, 0); else if (installed) d = ImageCache.addOverlay(d, ImageCache.IMG_BREAKPOINT_INSTALLED, 0, 8); if (warning) d = ImageCache.addOverlay(d, ImageCache.IMG_BREAKPOINT_WARNING, 9, 8); if (error) d = ImageCache.addOverlay(d, ImageCache.IMG_BREAKPOINT_ERROR, 9, 8); done(d); } }.getE(); } String cond = breakpoint.getMarker().getAttribute(TCFBreakpointsModel.ATTR_CONDITION, null); if (cond != null && cond.length() > 0) { descriptor = ImageCache.addOverlay(descriptor, ImageCache.IMG_BREAKPOINT_CONDITIONAL); } } catch (Throwable x) { } } if (descriptor != null) return ImageCache.getImage(descriptor); return null; } public String getText(Object element) { String text = null; if (element instanceof IBreakpoint) { final IBreakpoint breakpoint = (IBreakpoint)element; IMarker marker = breakpoint.getMarker(); if (marker == null) return null; StringBuffer bf = new StringBuffer(); try { Map<String,Object> m = marker.getAttributes(); String file = marker.getAttribute(TCFBreakpointsModel.ATTR_FILE, null); if (file != null && file.length() > 0) { IPath path = new Path(file); if (path.isValidPath(file)) { bf.append(isShowQualifiedNames() ? path.toOSString() : path.lastSegment()); bf.append(' '); } } for (int i = 0; i < attr_names.length; i += 2) { Object obj = m.get(attr_names[i]); if (obj == null) continue; String s = obj.toString(); if (s.length() == 0) continue; bf.append('['); bf.append(attr_names[i + 1]); bf.append(": "); bf.append(s); bf.append(']'); } String ct_inp = marker.getAttribute(TCFBreakpointsModel.ATTR_CT_INP, null); String ct_out = marker.getAttribute(TCFBreakpointsModel.ATTR_CT_OUT, null); if (ct_inp != null || ct_out != null) { bf.append("[cross trigger:"); if (ct_inp != null) { if (ct_inp.startsWith("JSON:")) ct_inp = ct_inp.substring(5); bf.append(" in "); bf.append(ct_inp); } if (ct_out != null) { if (ct_out.startsWith("JSON:")) ct_out = ct_out.substring(5); if (ct_inp != null) bf.append(','); bf.append(" out "); bf.append(ct_out); } bf.append(']'); } if (bf.length() == 0) { String id = marker.getAttribute(TCFBreakpointsModel.ATTR_ID, null); if (id == null) id = Long.toString(marker.getId()); bf.append(id); } } catch (Throwable x) { return x.toString(); } text = bf.toString(); String status = new TCFTask<String>() { public void run() { done(Activator.getAnnotationManager().getBreakpointStatusText(breakpoint)); } }.getE(); if (status != null) text += " (" + status + ")"; } return text; } protected boolean isShowQualifiedNames() { Boolean show_qualified = (Boolean)attrs.get( DISPLAY_FULL_PATHS ); if (show_qualified == null) return false; return show_qualified.booleanValue(); } public void setAttribute(String attribute, Object value) { if (value == null) attrs.remove(attribute); else attrs.put(attribute, value); } public boolean isLabelProperty(Object element, String property) { return true; } public String getEditorId(IEditorInput input, Object element) { String id = null; if (input != null) { IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry(); IEditorDescriptor descriptor = registry.getDefaultEditor(input.getName()); if (descriptor != null && !descriptor.isOpenExternal()) id = descriptor.getId(); else id = EditorsUI.DEFAULT_TEXT_EDITOR_ID; } return id; } public IEditorInput getEditorInput(Object element) { if (element instanceof ILineBreakpoint) { element = ((ILineBreakpoint)element).getMarker(); } if (element instanceof IMarker) { element = ((IMarker)element).getResource(); } if (element instanceof IFile) { return new FileEditorInput((IFile)element); } if (element instanceof IStorage) { IPath fullPath; if (element instanceof LocalFileStorage) { // Bug 390572: Don't use LocalFileStorage.getFullPath() as it resolves symlinks fullPath = new Path(((LocalFileStorage)element).getFile().getAbsolutePath()); } else { fullPath = ((IStorage)element).getFullPath(); } URI uri = URIUtil.toURI(fullPath); if (uri != null) { try { return new FileStoreEditorInput(EFS.getStore(uri)); } catch (CoreException e) { Activator.log(e); } } } return null; } }