/* * Copyright 2010 The Rabbit Eclipse Plug-in Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package rabbit.tracking.internal.trackers; import rabbit.data.handler.DataHandler; import rabbit.data.store.IStorer; import rabbit.data.store.model.LaunchEvent; import rabbit.tracking.internal.util.Recorder; import com.google.common.collect.Maps; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IThread; import org.joda.time.Interval; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Observable; import java.util.Observer; import java.util.Set; /** * Tracks launch events. */ public class LaunchTracker extends AbstractTracker<LaunchEvent> { private final IDebugEventSetListener listener = new IDebugEventSetListener() { @Override public void handleDebugEvents(DebugEvent[] events) { for (DebugEvent event : events) { handleDebugEvent(event); } } }; private final Observer observer = new Observer() { @Override public void update(Observable o, Object arg) { if (recorders.values().contains(o)) { @SuppressWarnings("unchecked") Recorder<ILaunch> recorder = (Recorder<ILaunch>) o; long start = recorder.getLastRecord().getStartTimeMillis(); long end = recorder.getLastRecord().getEndTimeMillis(); ILaunch launch = recorder.getLastRecord().getUserData(); ILaunchConfiguration config = launch.getLaunchConfiguration(); if (config == null) { return; } ILaunchConfigurationType type = null; try { type = config.getType(); } catch (CoreException e) { e.printStackTrace(); return; } Set<IPath> files = launchFiles.get(launch); if (files == null) { files = Collections.emptySet(); } Interval interval = new Interval(start, end); addData(new LaunchEvent(interval, launch, config, type, files)); } } }; /** A map of launches and the files involved (for debug launches). */ private final Map<ILaunch, Set<IPath>> launchFiles = Maps.newHashMap(); /** One recorder for each launch. */ private final Map<ILaunch, Recorder<ILaunch>> recorders = Maps.newHashMap(); /** * Constructs a new tracker. */ public LaunchTracker() { } @Override protected IStorer<LaunchEvent> createDataStorer() { return DataHandler.getStorer(LaunchEvent.class); } @Override protected void doDisable() { DebugPlugin debug = DebugPlugin.getDefault(); debug.removeDebugEventListener(listener); } @Override protected void doEnable() { DebugPlugin debug = DebugPlugin.getDefault(); debug.addDebugEventListener(listener); } /** * Handles an event. * * @param event The event. */ private void handleDebugEvent(DebugEvent event) { Object source = event.getSource(); if (source instanceof IProcess) { handleProcessEvent(event, (IProcess) source); } else if (source instanceof IThread) { handleThreadEvent(event, (IThread) source); } } /** * Handles the event who's source is an IProcess. * * @param event The event. * @param process The process of the event. */ private void handleProcessEvent(DebugEvent event, IProcess process) { ILaunch launch = process.getLaunch(); // Records the start time of this launch: if (event.getKind() == DebugEvent.CREATE) { Recorder<ILaunch> r = recorders.get(launch); if (r == null) { r = new Recorder<ILaunch>(); r.addObserver(observer); recorders.put(launch, r); } r.start(launch); } else if (event.getKind() == DebugEvent.TERMINATE) { Recorder<ILaunch> r = recorders.get(launch); if (r != null) { r.stop(); } } } /** * Handles an event who's source is an IThread. * * @param event The event. * @param thread The thread of the event. */ private void handleThreadEvent(DebugEvent event, IThread thread) { // We are only interested in SUSPEND events: if (event.getKind() != DebugEvent.SUSPEND) { return; } ILaunch launch = thread.getLaunch(); ILaunchConfiguration config = launch.getLaunchConfiguration(); if (config == null) { return; } IStackFrame stack = null; try { stack = thread.getTopStackFrame(); } catch (DebugException e) { return; } if (stack == null) { return; } ISourceLocator sourceLocator = launch.getSourceLocator(); if (sourceLocator == null) { return; } Object element = sourceLocator.getSourceElement(stack); // Element is a file in workspace, record it: if (element != null && element instanceof IFile) { IFile file = (IFile) element; Set<IPath> filePaths = launchFiles.get(launch); if (filePaths == null) { filePaths = new HashSet<IPath>(3); launchFiles.put(launch, filePaths); } filePaths.add(file.getFullPath()); } } }