/***************************************************************************** * Copyright (c) 2006, 2008 g-Eclipse Consortium * 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 * * Initial development of the original code was made for the * g-Eclipse project founded by European Union * project number: FP6-IST-034327 http://www.geclipse.eu/ * * Contributors: * Christof Klausecker GUP, JKU - initial API and implementation *****************************************************************************/ package eu.geclipse.traceview.debug; import java.util.Iterator; import java.util.Map; import java.util.SortedSet; import java.util.StringTokenizer; import java.util.TreeSet; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.debug.internal.core.breakpoints.AbstractLineBreakpoint; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import eu.geclipse.traceview.IEvent; import eu.geclipse.traceview.ISourceLocation; import eu.geclipse.traceview.ITrace; /** * A Breakpoint the suspends when an Event is reached. */ @SuppressWarnings("restriction") public class EventBreakpoint extends AbstractLineBreakpoint { /** Process */ public final static String PROCESS = "Process"; //$NON-NLS-1$ final static String IGNORE_COUNTS = "IgnoreCounts"; //$NON-NLS-1$ final static String TRACE_PATH = "TracePath"; //$NON-NLS-1$ final static String NUM_PROCS = "NumProcs"; //$NON-NLS-1$ final static String PROJ_NAME = "ProjName"; //$NON-NLS-1$ private boolean alive; private int position; /** * Constructor for EventBreakpoint. */ public EventBreakpoint() { this.position = 0; this.alive = true; } /** * Constructor for EventBreakpoint. * * @param resource * @param attributes * @param register * @param event * @throws CoreException */ @SuppressWarnings({ "unchecked" }) public EventBreakpoint( final IResource resource, final Map attributes, final boolean register, final IEvent event ) throws CoreException { super( resource, getMarkerType(), attributes, register ); this.position = 0; this.alive = true; String tracePath = event.getProcess().getTrace().getPath().toString(); String projectName = getProject( event.getProcess().getTrace() ).getProject().getName(); int numberOfProcesses = event.getProcess().getTrace().getNumberOfProcesses(); int process = event.getProcessId(); ensureMarker().setAttribute( TRACE_PATH, tracePath ); ensureMarker().setAttribute( PROJ_NAME, projectName ); ensureMarker().setAttribute( NUM_PROCS, numberOfProcesses ); ensureMarker().setAttribute( PROCESS, process ); } /** * Returns the Marker for this Breakpoint * * @return the Marker for this Breakpoint */ public static String getMarkerType() { return "eu.geclipse.traceview.debug.BreakpointMarker"; //$NON-NLS-1$ } @Override public int getIgnoreCount() throws CoreException { if( this.alive == true ) { setIgnoreCount( getIgnoreCounts().first().intValue() ); this.alive = false; } return super.getIgnoreCount(); } /** * Returns the Project which contains the Trace * * @param trace * @return project */ protected ICProject getProject( final ITrace trace ) { ICProject project = null; IPath tracePath = trace.getPath(); // check if the trace is located in the workspace boolean workspace = ResourcesPlugin.getWorkspace().getRoot().getLocation().isPrefixOf( tracePath ); if( workspace ) { IPath path = tracePath.removeFirstSegments( ResourcesPlugin.getWorkspace().getRoot().getLocation().segmentCount() ); // get the name of the project the trace is located in String projectName = path.uptoSegment( 1 ).toPortableString(); String device = path.getDevice(); if( device != null ) { projectName = projectName.substring( device.length() ); } // get the project if( projectName != null && projectName.length() > 0 ) { project = CoreModel.getDefault().getCModel().getCProject( projectName ); } } return project; } /** * Returns the number of processes * * @return number of processes * @throws CoreException */ public int getNumberOfProcesses() throws CoreException { return this.ensureMarker().getAttribute( NUM_PROCS, -1 ); } /** * Returns the process this breakpoint is assigned to. * * @return assigned process * @throws CoreException */ public int getProcess() throws CoreException { return this.ensureMarker().getAttribute( PROCESS, -1 ); } /** * Returns the Path of the Trace * * @return trace path * @throws CoreException */ public String getTracePath() throws CoreException { return this.ensureMarker().getAttribute( TRACE_PATH, "" ); //$NON-NLS-1$ } /** * Returns the name of the project * * @return project name * @throws CoreException */ public String getProjectName() throws CoreException { return this.ensureMarker().getAttribute( PROJ_NAME, "" ); //$NON-NLS-1$ } /** * Revives a EventBreakpoint at the end */ public void revive() { if( !this.alive ) { this.alive = true; try { this.setEnabled( true ); } catch( CoreException coreException ) { Activator.logException( coreException ); } } } private SortedSet<Integer> getIgnoreCounts() throws CoreException { String countString = this.ensureMarker().getAttribute( IGNORE_COUNTS, "" ); //$NON-NLS-1$ StringTokenizer tokenizer = new StringTokenizer( countString ); SortedSet<Integer> counts = new TreeSet<Integer>(); while( tokenizer.hasMoreTokens() ) { counts.add( Integer.valueOf( Integer.parseInt( tokenizer.nextToken() ) ) ); } return counts; } private void setIgnoreCounts( final SortedSet<Integer> ignoreCounts ) throws DebugException, CoreException { if( !ignoreCounts.isEmpty() ) { setIgnoreCount( ignoreCounts.first().intValue() ); } Iterator<Integer> it = ignoreCounts.iterator(); StringBuffer buffer = new StringBuffer(); while( it.hasNext() ) { buffer.append( it.next().toString() + " " ); //$NON-NLS-1$ // System.out.println( buffer.toString() ); } ensureMarker().setAttribute( IGNORE_COUNTS, buffer.toString() ); } /** * Checks if the EventBreakpoint is active for the IEvent * * @param event * @return true if Breakpoint contains Event * @throws CoreException */ public boolean containtsEvent( final IEvent event ) throws CoreException { SortedSet<Integer> ignoreCounts = this.getIgnoreCounts(); boolean result = false; Iterator<Integer> it = ignoreCounts.iterator(); if( event.getProcessId() == this.getProcess() ) { while( !result && it.hasNext() ) { ISourceLocation sourceLocation = ( ISourceLocation )event; if( it.next().intValue() == sourceLocation.getOccurrenceCount() && this.getLineNumber() == sourceLocation.getSourceLineNumber() ) { result = true; } } } return result; } /** * Adds an Event to the Breakpoint * * @param event * @throws CoreException */ public void addEvent( final IEvent event ) throws CoreException { if( event instanceof ISourceLocation ) { ISourceLocation sourceLocation = ( ISourceLocation )event; SortedSet<Integer> ignoreCounts = this.getIgnoreCounts(); if( ignoreCounts.add( Integer.valueOf( sourceLocation.getOccurrenceCount() ) ) ) { setIgnoreCounts( ignoreCounts ); } } } /** * Removes an Event from the Breakpoint * * @param event * @throws CoreException */ public void removeEvent( final IEvent event ) throws CoreException { if( event instanceof ISourceLocation ) { ISourceLocation sourceLocation = ( ISourceLocation )event; SortedSet<Integer> ignoreCounts = getIgnoreCounts(); if( ignoreCounts.remove( Integer.valueOf( sourceLocation.getOccurrenceCount() ) ) ) { setIgnoreCounts( ignoreCounts ); if( ignoreCounts.isEmpty() ) { DebugPlugin.getDefault().getBreakpointManager().removeBreakpoint( this, true ); } } } } /** * Switches to the next Event * * @throws CoreException */ public void next() throws CoreException { Integer[] ignoreCounts = getIgnoreCounts().toArray( new Integer[ 0 ] ); if( ignoreCounts.length > this.position + 1 ) { setIgnoreCount( ignoreCounts[ this.position + 1 ].intValue() - ignoreCounts[ this.position++ ].intValue() - 1 ); } else { setEnabled( false ); } } @Override protected String getMarkerMessage() throws CoreException { String result = "breakpoint: process " + getProcess(); return result; } }