| /******************************************************************************* |
| * Copyright (c) 2009, 2010 Nokia 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: |
| * Nokia - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.edc.internal.snapshot; |
| |
| import java.io.BufferedInputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipOutputStream; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.TransformerException; |
| |
| import org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer; |
| import org.eclipse.cdt.debug.edc.internal.EDCDebugger; |
| import org.eclipse.cdt.debug.edc.internal.PathUtils; |
| import org.eclipse.cdt.debug.edc.internal.ZipFileUtils; |
| import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl; |
| import org.eclipse.cdt.debug.edc.launch.EDCLaunch; |
| import org.eclipse.cdt.debug.edc.services.Stack; |
| import org.eclipse.cdt.debug.edc.services.Stack.StackFrameDMC; |
| import org.eclipse.cdt.debug.edc.snapshot.IAlbum; |
| import org.eclipse.cdt.debug.internal.core.sourcelookup.MapEntrySourceContainer; |
| import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
| import org.eclipse.cdt.dsf.concurrent.DsfRunnable; |
| import org.eclipse.cdt.dsf.concurrent.Query; |
| import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; |
| import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; |
| import org.eclipse.cdt.dsf.service.DsfServicesTracker; |
| import org.eclipse.cdt.dsf.service.DsfSession; |
| import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.FileLocator; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.PlatformObject; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.SubMonitor; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.sourcelookup.ISourceContainer; |
| import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; |
| import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer; |
| import org.eclipse.debug.internal.core.LaunchManager; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.prefs.BackingStoreException; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| /** |
| * The Album class represents a series of snapshots that record moments in a |
| * debug session. An Album manages the collection of snapshots, common resources |
| * such as source files, persistence, and association with debug sessions. |
| * |
| * An Album is usually created during a debug session, saved at the conclusion |
| * of the session, and reopened by a launch delegate for a new snapshot debug |
| * session. |
| * |
| * When an Album is saved it's data and resources are archived in a snapshot |
| * file in a default location. When reopened the contents are expanded into a |
| * temporary directory and used to recreate the debug session. |
| */ |
| @SuppressWarnings("restriction") |
| public class Album extends PlatformObject implements IAlbum { |
| |
| // XML element names |
| public static final String SNAPSHOT = "snapshot"; |
| private static final String ALBUM = "album"; |
| private static final String LAUNCH = "launch"; |
| private static final String RESOURCES = "resources"; |
| private static final String FILE = "file"; |
| private static final String INFO = "info"; |
| |
| public static final String METADATA = "snapshotMetaData"; |
| public static final String SNAPSHOT_LIST = "snapshots"; |
| |
| private static final String ALBUM_DATA = "album.xml"; |
| private static final String ALBUM_VERSION = "100"; |
| |
| private static String[] DSA_FILE_EXTENSIONS = new String[] {"dsa"}; |
| |
| // Preferences |
| public static final String PREF_CREATION_CONTROL = "creation_control"; |
| public static final String CREATE_MANUAL = "manual"; |
| public static final String CREATE_WHEN_STOPPED = "suspend"; |
| public static final String CREATE_AT_BEAKPOINTS = "breakpoints"; |
| |
| public static final String PREF_VARIABLE_CAPTURE_DEPTH = "variable_capture_depth"; |
| public static final String PLAY_SNAPSHOT_DELAY_TIME = "play_snapshot_delay_time"; |
| |
| private static final String CAMERA_CLICK_WAV = "/sounds/camera_click.wav"; |
| |
| private Document document; |
| private Element albumRootElement; |
| |
| private final List<Snapshot> snapshotList = new ArrayList<Snapshot>(); |
| private String sessionID = ""; |
| private String recordingSessionID = ""; |
| private IPath albumRootDirectory; |
| private boolean launchConfigSaved; |
| private String launchType; |
| private HashMap<String, Object> launchProperties; |
| private String launchName = ""; |
| private String name; |
| private boolean loaded; |
| private boolean metaDataLoaded; |
| private final Set<IPath> files = new HashSet<IPath>(); |
| |
| private int currentSnapshotIndex; |
| private IPath location; |
| private boolean resourceListSaved; |
| private boolean metadataSaved; |
| private boolean albumInfoSaved; |
| private String displayName; |
| private boolean playingSnapshots; |
| |
| /** |
| * Listener for state changes on albums |
| */ |
| protected static List<ISnapshotAlbumEventListener> listeners = Collections.synchronizedList(new ArrayList<ISnapshotAlbumEventListener>()); |
| |
| private static Map<String, Album> albumsBySessionID = Collections.synchronizedMap(new HashMap<String, Album>()); |
| private static Map<String, Album> albumsRecordingBySessionID = Collections.synchronizedMap(new HashMap<String, Album>()); |
| private static Map<IPath, Album> albumsByLocation = Collections.synchronizedMap(new HashMap<IPath, Album>()); |
| private static Map<String, Integer> launchNames = Collections.synchronizedMap(new HashMap<String, Integer>()); |
| |
| private static boolean sessionEndedListenerAdded; |
| private static SessionEndedListener sessionEndedListener = new SessionEndedListener() { |
| |
| public void sessionEnded(DsfSession session) { |
| Album album = albumsRecordingBySessionID.get(session.getId()); |
| if (album == null) |
| album = albumsBySessionID.get(session.getId()); |
| if (album != null && session.getId().equals(album.getRecordingSessionID())) { |
| album.saveResources(new NullProgressMonitor()); |
| album.setRecordingSessionID(""); |
| } |
| synchronized (albumsRecordingBySessionID) { |
| albumsRecordingBySessionID.remove(session.getId()); |
| } |
| synchronized (albumsBySessionID) { |
| albumsBySessionID.remove(session.getId()); |
| } |
| |
| if (album != null) { |
| for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) { |
| l.snapshotSessionEnded(album, session); |
| } |
| } |
| } |
| }; |
| |
| public interface IAlbumArchiveEntry { |
| |
| public String createEntryName(File file); |
| |
| } |
| |
| public Album() { |
| super(); |
| try { |
| setDocument(DebugPlugin.newDocument()); |
| if (!sessionEndedListenerAdded) |
| DsfSession.addSessionEndedListener(sessionEndedListener); |
| sessionEndedListenerAdded = true; |
| } catch (CoreException e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getName() |
| */ |
| public String getName() { |
| if (name == null) { |
| name = getDefaultAlbumName(); |
| } |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public void setDisplayName(String displayName) { |
| this.displayName = displayName; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getDisplayName() |
| */ |
| public String getDisplayName() { |
| if (displayName == null || displayName.length() == 0) { |
| displayName = getName(); |
| } |
| return displayName; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSessionID() |
| */ |
| public String getSessionID() { |
| sessionID = ""; |
| if (albumsBySessionID != null) { |
| for (Map.Entry<String, Album> entry : albumsBySessionID.entrySet()){ |
| if (entry.getValue().location != null && entry.getValue().location.equals(getLocation())){ |
| sessionID = entry.getKey(); |
| } |
| } |
| } |
| return sessionID; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getRecordingSessionID() |
| */ |
| public String getRecordingSessionID() { |
| return recordingSessionID; |
| } |
| |
| public void setRecordingSessionID(String sessionID) { |
| this.recordingSessionID = sessionID; |
| if (sessionID.length() > 0) |
| albumsRecordingBySessionID.put(sessionID, this); |
| } |
| |
| public void setSessionID(String sessionID) { |
| this.sessionID = sessionID; |
| if (sessionID.length() > 0) |
| albumsBySessionID.put(sessionID, this); |
| } |
| |
| /** |
| * Is the album currently open for recording |
| * @param sessionId |
| * @return true if the album is currently being recording by an active debug session |
| */ |
| public static boolean isSnapshotSession(String sessionId) { |
| EDCLaunch launch = EDCLaunch.getLaunchForSession(sessionId); |
| return launch != null && launch.isSnapshotLaunch(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#createSnapshot(org.eclipse.cdt.dsf.service.DsfSession, org.eclipse.cdt.debug.edc.internal.services.dsf.Stack.StackFrameDMC, org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public Snapshot createSnapshot(DsfSession session, StackFrameDMC stackFrame, IProgressMonitor monitor) throws Exception { |
| SubMonitor progress = SubMonitor.convert(monitor, "Creating Snapshot", 10000); |
| configureAlbum(); |
| progress.worked(100); |
| |
| if (getLocation() == null || !getLocation().toFile().exists()){ |
| createEmptyAlbum(); |
| } |
| |
| Snapshot snapshot = new Snapshot(this, session, stackFrame); |
| snapshot.writeSnapshotData(progress.newChild(7900)); |
| |
| snapshotList.add(snapshot); |
| saveAlbum(progress.newChild(1000)); |
| |
| monitor.done(); |
| return snapshot; |
| } |
| |
| private void configureAlbum() { |
| saveAlbumInfo(); |
| saveLaunchConfiguration(); |
| } |
| |
| private void saveAlbumInfo() { |
| if (!albumInfoSaved) { |
| Element infoElement = document.createElement(INFO); |
| infoElement.setAttribute("version", ALBUM_VERSION); |
| Calendar calendar = Calendar.getInstance(); |
| infoElement.setAttribute("month", Integer.toString(calendar.get(Calendar.MONTH))); |
| infoElement.setAttribute("day", Integer.toString(calendar.get(Calendar.DATE))); |
| infoElement.setAttribute("year", Integer.toString(calendar.get(Calendar.YEAR))); |
| infoElement.setAttribute("hour", Integer.toString(calendar.get(Calendar.HOUR))); |
| infoElement.setAttribute("minute", Integer.toString(calendar.get(Calendar.MINUTE))); |
| infoElement.setAttribute("second", Integer.toString(calendar.get(Calendar.SECOND))); |
| |
| Properties systemProps = System.getProperties(); |
| Map<String, Object> infoProps = new HashMap<String, Object>(); |
| Set<Object> systemKeys = systemProps.keySet(); |
| |
| for (Object sysKey : systemKeys) { |
| if (sysKey instanceof String) |
| infoProps.put((String) sysKey, systemProps.get(sysKey)); |
| } |
| Element propsElement = SnapshotUtils.makeXMLFromProperties(document, infoProps); |
| infoElement.appendChild(propsElement); |
| |
| getAlbumRootElement().appendChild(infoElement); |
| albumInfoSaved = true; |
| } |
| } |
| |
| private void saveResourceList() { |
| if (!resourceListSaved) { |
| Element resourcesElement = document.createElement(RESOURCES); |
| for (IPath filePath : files) { |
| Element fileElement = document.createElement(FILE); |
| fileElement.setAttribute("path", filePath.toOSString()); |
| resourcesElement.appendChild(fileElement); |
| } |
| getAlbumRootElement().appendChild(resourcesElement); |
| resourceListSaved = true; |
| } |
| } |
| |
| private void saveSnapshotMetadata() { |
| if (!metadataSaved || isRecording()) { |
| |
| if (metadataSaved){ |
| // If metatdata is saved, it must be a live debug session so |
| // we need to add a new snapshot to the snapshot list |
| NodeList snapMetaDataNode = document.getElementsByTagName(METADATA); |
| assert snapMetaDataNode.item(0) != null; |
| document.getDocumentElement().removeChild(snapMetaDataNode.item(0)); |
| } |
| |
| Element metadataElement = document.createElement(METADATA); |
| |
| Element albumElement = document.createElement(ALBUM); |
| albumElement.setAttribute("albumName", this.getDisplayName()); |
| metadataElement.appendChild(albumElement); |
| |
| Element snapshotsElement = document.createElement(SNAPSHOT_LIST); |
| metadataElement.appendChild(snapshotsElement); |
| |
| for (Snapshot snap : snapshotList) { |
| Element snapshotMetadataElement = document.createElement(SNAPSHOT); |
| if (snap.getSnapshotDisplayName().length() == 0) { |
| snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotFileName()); |
| } else { |
| snapshotMetadataElement.setAttribute("displayName", snap.getSnapshotDisplayName()); |
| } |
| if (snap.getCreationDate() != null) { |
| snapshotMetadataElement.setAttribute("date", snap.getCreationDate().toString()); |
| } else { |
| snapshotMetadataElement.setAttribute("date", "unknown"); |
| } |
| |
| snapshotMetadataElement.setAttribute("description", snap.getSnapshotDescription()); |
| snapshotMetadataElement.setAttribute("fileName", snap.getSnapshotFileName()); |
| snapshotMetadataElement.setAttribute("referenceLocationSourceFile", snap.getReferenceLocationSourceFile()); |
| snapshotMetadataElement.setAttribute("referenceLocationLineNumber", String.valueOf(snap.getReferenceLocationLineNumber())); |
| |
| snapshotsElement.appendChild(snapshotMetadataElement); |
| } |
| getAlbumRootElement().appendChild(metadataElement); |
| metadataSaved = true; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void saveLaunchConfiguration() { |
| if (!launchConfigSaved) { |
| EDCLaunch launch = EDCLaunch.getLaunchForSession(getRecordingSessionID()); |
| try { |
| Map<String, Object> map = launch.getLaunchConfiguration().getAttributes(); |
| Element launchElement = document.createElement(LAUNCH); |
| launchType = launch.getLaunchConfiguration().getType().getIdentifier(); |
| launchName = launch.getLaunchConfiguration().getName(); |
| Integer count = launchNames.get(launchName); |
| if (count == null) { |
| launchNames.put(launchName, new Integer(0)); |
| } |
| else { |
| count = new Integer(count.intValue() + 1); |
| launchNames.put(launchName, count); |
| launchName += " (" + count.toString() + ")"; |
| } |
| launchElement.setAttribute("type", launchType); |
| launchElement.setAttribute("name", launchName); |
| Element propsElement = SnapshotUtils.makeXMLFromProperties(document, map); |
| launchElement.appendChild(propsElement); |
| getAlbumRootElement().appendChild(launchElement); |
| } catch (CoreException e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| launchConfigSaved = true; |
| } |
| } |
| |
| private static void addZipEntry(ZipOutputStream zipOut, IAlbumArchiveEntry entry, File file) |
| throws FileNotFoundException, IOException { |
| if (file.exists()) { |
| if (file.isDirectory()) { |
| for (File child : file.listFiles()) { |
| addZipEntry(zipOut, entry, child); |
| } |
| } else { |
| // Add ZIP entry to output stream.m |
| String path = ""; //$NON-NLS-1$ |
| |
| if (entry != null) { |
| path = entry.createEntryName(file); |
| } else { |
| path = file.getName(); |
| } |
| |
| zipOut.putNextEntry(new ZipEntry(path)); |
| |
| // Create a buffer for reading the files |
| byte[] buf = new byte[1024]; |
| |
| // Transfer bytes from the file to the ZIP file |
| // and compress the files |
| FileInputStream in = new FileInputStream(file); |
| int len; |
| while ((len = in.read(buf)) > 0) { |
| zipOut.write(buf, 0, len); |
| } |
| |
| // Complete the entry |
| zipOut.closeEntry(); |
| in.close(); |
| } |
| } |
| } |
| |
| /** |
| * Create and write a full snapshot album from scratch |
| */ |
| private void saveAlbum(IProgressMonitor monitor) { |
| |
| IPath zipPath = getLocation(); |
| ZipOutputStream zipOut = null; |
| try { |
| SubMonitor progress = SubMonitor.convert(monitor, 2000 + (snapshotList.size() * 1000)); |
| progress.subTask("Saving album data"); |
| |
| zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile())); |
| |
| zipOut.putNextEntry(new ZipEntry(ALBUM_DATA)); |
| |
| saveResourceList(); |
| progress.worked(1000); |
| saveSnapshotMetadata(); |
| progress.worked(1000); |
| |
| String xml = LaunchManager.serializeDocument(document); |
| zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$ |
| zipOut.closeEntry(); |
| |
| for (Snapshot snap : snapshotList) { |
| zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName())); |
| snap.saveSnapshot(zipOut); |
| progress.worked(1000); |
| } |
| |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } finally { |
| try { |
| if (zipOut != null) { |
| zipOut.close(); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| /** |
| * Create and write a full snapshot album from scratch |
| */ |
| private void saveResources(IProgressMonitor monitor) { |
| |
| IPath zipPath = getLocation(); |
| ZipOutputStream zipOut = null; |
| try { |
| // TODO: Here's we're just rewriting the entire album again |
| // Need to just add the resources alone using proper utils |
| zipOut = new ZipOutputStream(new FileOutputStream(zipPath.toFile())); |
| |
| for (IPath path : files) { |
| |
| IAlbumArchiveEntry entry = new IAlbumArchiveEntry() { |
| |
| public String createEntryName(File file) { |
| StringBuffer entryPath = new StringBuffer(); |
| |
| entryPath.append("Resources/"); |
| |
| IPath filepath = new Path(file.getAbsolutePath()); |
| |
| String deviceName = filepath.getDevice(); |
| if (deviceName != null) { |
| // Remove the : from the end |
| entryPath.append(deviceName.substring(0, deviceName.length() - 1)); |
| entryPath.append("/"); |
| } |
| |
| String[] segments = filepath.segments(); |
| int numSegments = segments.length - 1; |
| |
| for (int i = 0; i < numSegments; i++) { |
| entryPath.append(segments[i]); |
| entryPath.append("/"); |
| } |
| entryPath.append(file.getName()); |
| return entryPath.toString(); |
| } |
| }; |
| addZipEntry(zipOut, entry, path.toFile()); |
| if (monitor != null) { |
| monitor.worked(1); |
| } |
| } |
| zipOut.putNextEntry(new ZipEntry(ALBUM_DATA)); |
| |
| saveResourceList(); |
| saveSnapshotMetadata(); |
| |
| String xml = LaunchManager.serializeDocument(document); |
| zipOut.write(xml.getBytes("UTF8")); //$NON-NLS-1$ |
| zipOut.closeEntry(); |
| |
| for (Snapshot snap : snapshotList) { |
| zipOut.putNextEntry(new ZipEntry(snap.getSnapshotFileName())); |
| snap.saveSnapshot(zipOut); |
| } |
| |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } finally { |
| try { |
| if (zipOut != null) { |
| zipOut.close(); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| |
| private String getDefaultAlbumName() { |
| return getLaunchName(); |
| } |
| |
| public void saveAlbum(IPath path) throws TransformerException, IOException { |
| String xml = LaunchManager.serializeDocument(document); |
| File file = path.toFile(); |
| if (!file.exists()) { |
| file.createNewFile(); |
| } |
| FileOutputStream stream = new FileOutputStream(file); |
| stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$ |
| stream.close(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openSnapshot(int) |
| */ |
| public void openSnapshot(final int index) { |
| |
| final DsfSession session = DsfSession.getSession(sessionID); |
| |
| DsfRunnable openIt = new DsfRunnable() { |
| public void run() { |
| currentSnapshotIndex = index; |
| try { |
| loadAlbum(false); |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| if (session != null && snapshotList.size() > index) { |
| Snapshot snapshot = snapshotList.get(index); |
| snapshot.open(session); |
| // Fire the event |
| for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) { |
| l.snapshotOpened(snapshot); |
| } |
| } |
| } |
| }; |
| |
| if (session != null && session.getExecutor() != null) |
| { |
| if (session.getExecutor().isInExecutorThread()) |
| openIt.run(); |
| else |
| session.getExecutor().execute(openIt); |
| } |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getCurrentSnapshotIndex() |
| */ |
| public int getCurrentSnapshotIndex() { |
| return currentSnapshotIndex; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openNextSnapshot() |
| */ |
| public void openNextSnapshot() throws Exception { |
| int nextIndex = currentSnapshotIndex + 1; |
| if (nextIndex >= snapshotList.size()) |
| nextIndex = 0; |
| openSnapshot(nextIndex); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#openPreviousSnapshot() |
| */ |
| public void openPreviousSnapshot() throws Exception { |
| int previousIndex = currentSnapshotIndex - 1; |
| if (previousIndex < 0) |
| previousIndex = snapshotList.size() - 1; |
| openSnapshot(previousIndex); |
| } |
| |
| public void loadAlbum(boolean force) throws ParserConfigurationException, SAXException, IOException { |
| if (force) |
| loaded = false; |
| if (!loaded) { |
| File albumFile = location.toFile(); |
| setName(albumFile.getName()); |
| |
| if (!isRecording()){ |
| // not creating the snapshot, so must be snapshot play back |
| try { |
| ZipFileUtils.unzipFiles(albumFile, getAlbumRootDirectory().toOSString(), new NullProgressMonitor()); |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| } |
| |
| BufferedInputStream stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS); |
| DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| parser.setErrorHandler(new DefaultHandler()); |
| InputSource inputSource = new InputSource(stream); |
| inputSource.setSystemId(albumFile.toURI().toString()); // avoid NPE inside XML parser |
| setDocument(parser.parse(inputSource)); |
| |
| loadAlbumInfo(); |
| loadLaunchConfiguration(); |
| loadResourceList(); |
| try { |
| loadSnapshotMetadata(); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } finally { |
| loaded = true; |
| ZipFileUtils.unmount(); |
| } |
| } |
| } |
| |
| /** |
| * A lightwieght parse to get basic album info and what snapshots are |
| * available. |
| * |
| * @throws ParserConfigurationException |
| * @throws SAXException |
| * @throws IOException |
| */ |
| public void loadAlbumMetada(boolean force) throws Exception { |
| if (force) |
| metaDataLoaded = false; |
| if (!metaDataLoaded) { |
| |
| File albumFile = location.toFile(); |
| setDisplayName(albumFile.getName()); |
| |
| BufferedInputStream stream = null; |
| try { |
| stream = ZipFileUtils.openFile(albumFile, ALBUM_DATA, DSA_FILE_EXTENSIONS); |
| DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| parser.setErrorHandler(new DefaultHandler()); |
| setDocument(parser.parse(new InputSource(stream))); |
| loadSnapshotMetadata(); |
| loadLaunchConfiguration(); // need to load launch config in case we need to delete it |
| |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError("Failed to load album: " + getName(), e); |
| } finally { |
| metaDataLoaded = true; |
| ZipFileUtils.unmount(); |
| } |
| } |
| } |
| |
| private void loadAlbumInfo() { |
| document.getElementsByTagName(INFO).item(0); |
| } |
| |
| private void setDocument(Document newDoc) |
| { |
| document = newDoc; |
| albumRootElement = null; |
| } |
| |
| private Element getAlbumRootElement() |
| { |
| if (albumRootElement == null) |
| { |
| NodeList albumRootElements = document.getElementsByTagName(ALBUM); |
| if (albumRootElements.getLength() == 0) |
| { |
| albumRootElement = document.createElement(ALBUM); |
| document.appendChild(albumRootElement); |
| } |
| else |
| { |
| albumRootElement = (Element) albumRootElements.item(0); |
| } |
| } |
| return albumRootElement; |
| } |
| |
| private void loadResourceList() { |
| NodeList resources = document.getElementsByTagName(RESOURCES); |
| NodeList elementFiles = ((Element) resources.item(0)).getElementsByTagName(FILE); |
| int numFiles = elementFiles.getLength(); |
| for (int i = 0; i < numFiles; i++) { |
| Element fileElement = (Element) elementFiles.item(i); |
| String elementPath = fileElement.getAttribute("path"); |
| files.add(PathUtils.createPath(elementPath)); // for cross-created snapshot |
| } |
| } |
| |
| private void loadSnapshotMetadata() throws Exception { |
| snapshotList.clear(); |
| NodeList snapMetaDataNode = document.getElementsByTagName(METADATA); |
| |
| if (snapMetaDataNode.getLength() == 0) { |
| throw new Exception("Invalid or corrupted Album : " + getName()); |
| } |
| NodeList albumNameElement = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM); |
| Element albumElement = (Element) albumNameElement.item(0); |
| String albumDisplayName = albumElement.getAttribute("albumName"); |
| |
| setDisplayName(albumDisplayName); |
| |
| NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT); |
| int numSnapshots = elementSnapshots.getLength(); |
| for (int i = 0; i < numSnapshots; i++) { |
| Element snapshotElement = (Element) elementSnapshots.item(i); |
| String elementDescription = snapshotElement.getAttribute("description"); |
| String elementDate = snapshotElement.getAttribute("date"); |
| String elementDispalyName = snapshotElement.getAttribute("displayName"); |
| String elementFileName = snapshotElement.getAttribute("fileName"); |
| String referenceLocationSourceFile = snapshotElement.getAttribute("referenceLocationSourceFile"); |
| String referenceLocationLineNumber = snapshotElement.getAttribute("referenceLocationLineNumber"); |
| |
| Snapshot s = new Snapshot(this); |
| s.setCreationDate(elementDate); |
| s.setSnapshotFileName(elementFileName); |
| s.setSnapshotDisplayName(elementDispalyName); |
| s.setSnapshotDescription(elementDescription); |
| if (referenceLocationLineNumber.length() > 0){ |
| s.setReferenceLocationLineNumber(Long.parseLong(referenceLocationLineNumber)); |
| } |
| s.setReferenceLocationSourceFile(referenceLocationSourceFile); |
| snapshotList.add(s); |
| } |
| } |
| |
| private void loadLaunchConfiguration() { |
| NodeList launchElements = document.getElementsByTagName(LAUNCH); |
| Element launchElement = (Element) launchElements.item(0); |
| if (launchElement == null){ |
| return; |
| } |
| launchType = launchElement.getAttribute("type"); |
| launchName = launchElement.getAttribute("name"); |
| |
| Element propElement = (Element) launchElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0); |
| launchProperties = new HashMap<String, Object>(); |
| try { |
| SnapshotUtils.initializeFromXML(propElement, launchProperties); |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| |
| } |
| |
| @SuppressWarnings("rawtypes") |
| @Override |
| public Object getAdapter(Class adapter) { |
| if (adapter.equals(Document.class)) |
| return document; |
| |
| return super.getAdapter(adapter); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getAlbumRootDirectory() |
| */ |
| public IPath getAlbumRootDirectory() { |
| if (albumRootDirectory == null) { |
| IPath path = EDCDebugger.getDefault().getStateLocation().append("SnapshotAlbums"); |
| String locationName = location.lastSegment(); |
| int extension = locationName.lastIndexOf("."); |
| if (extension > 0) { |
| locationName = locationName.substring(0, extension); |
| } |
| path = path.append(locationName); |
| File dir = path.toFile(); |
| if (!dir.exists()) { |
| dir.mkdirs(); |
| } |
| albumRootDirectory = path; |
| } |
| return albumRootDirectory; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchTypeID() |
| */ |
| public String getLaunchTypeID() { |
| return launchType; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchProperties() |
| */ |
| public HashMap<String, Object> getLaunchProperties() { |
| return launchProperties; |
| } |
| |
| public void setLaunchProperties(HashMap<String, Object> launchProperties) { |
| this.launchProperties = launchProperties; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLaunchName() |
| */ |
| public String getLaunchName() { |
| return launchName; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#playSnapshots(org.eclipse.cdt.dsf.service.DsfSession) |
| */ |
| public void playSnapshots() { |
| if (!isPlayingSnapshots()) |
| { |
| Job playSnapshotsJob = new Job("Play Snapshots for Album " + getDisplayName()){ |
| |
| @Override |
| protected IStatus run(IProgressMonitor monitor) { |
| try { |
| monitor.beginTask("Play Snapshots for Album " + getDisplayName(), IProgressMonitor.UNKNOWN); |
| while (isPlayingSnapshots() && !monitor.isCanceled()) |
| { |
| Album.this.openNextSnapshot(); |
| Thread.sleep(getPlaySnapshotInterval()); |
| } |
| setPlayingSnapshots(false); |
| monitor.done(); |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| return new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, null, e); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| }; |
| setPlayingSnapshots(true); |
| playSnapshotsJob.schedule(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#addFile(org.eclipse.core.runtime.IPath) |
| */ |
| public void addFile(IPath path) { |
| files.add(path); |
| } |
| |
| public static Album getAlbumByLocation(IPath path) { |
| return albumsByLocation.get(path); |
| } |
| |
| public static IAlbum getAlbumBySession(String sessionId) { |
| return albumsBySessionID.get(sessionId); |
| } |
| |
| public static Album getRecordingForSession(String sessionId) { |
| return albumsRecordingBySessionID.get(sessionId); |
| } |
| |
| public void setLocation(IPath albumPath) { |
| this.location = albumPath; |
| albumsByLocation.put(albumPath, this); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getLocation() |
| */ |
| public IPath getLocation() { |
| return location; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureSourceLookupDirector(org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector) |
| */ |
| public void configureSourceLookupDirector(ISourceLookupDirector director) { |
| MappingSourceContainer sourceContainer = new MappingSourceContainer(getName()); |
| configureMappingSourceContainer(sourceContainer); |
| ArrayList<ISourceContainer> containers = new ArrayList<ISourceContainer>(Arrays.asList(director |
| .getSourceContainers())); |
| containers.add(sourceContainer); |
| |
| DirectorySourceContainer directoryContainer = new DirectorySourceContainer(getResourcesDirectory(), true); |
| containers.add(directoryContainer); |
| |
| director.setSourceContainers(containers.toArray(new ISourceContainer[containers.size()])); |
| } |
| |
| protected IPath getResourcesDirectory() |
| { |
| return getAlbumRootDirectory().append("Resources"); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#configureMappingSourceContainer(org.eclipse.cdt.debug.core.sourcelookup.MappingSourceContainer) |
| */ |
| public void configureMappingSourceContainer(MappingSourceContainer mappingContainer) { |
| IPath albumRoot = getResourcesDirectory(); |
| List<MapEntrySourceContainer> containers = new ArrayList<MapEntrySourceContainer>(); |
| Set<String> devicesAlreadyAdded = new HashSet<String>(); |
| String deviceName = null; |
| for (IPath iPath : files) { |
| deviceName = iPath.getDevice(); |
| if (deviceName != null && !devicesAlreadyAdded.contains(deviceName)) |
| { |
| String albumRootSuffix = deviceName; |
| if (albumRootSuffix.endsWith(":")) |
| albumRootSuffix = albumRootSuffix.substring(0, albumRootSuffix.length() - 1); |
| devicesAlreadyAdded.add(deviceName); |
| MapEntrySourceContainer newContainer = new MapEntrySourceContainer(PathUtils.createPath(deviceName), albumRoot.append(albumRootSuffix)); |
| containers.add(newContainer); |
| |
| } |
| } |
| mappingContainer.addMapEntries(containers.toArray(new MapEntrySourceContainer[containers.size()])); |
| } |
| |
| public static void setVariableCaptureDepth(int newSetting) { |
| IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID); |
| scope.putInt(PREF_VARIABLE_CAPTURE_DEPTH, newSetting); |
| try { |
| scope.flush(); |
| } catch (BackingStoreException e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| } |
| |
| public static int getVariableCaptureDepth() { |
| return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID, |
| PREF_VARIABLE_CAPTURE_DEPTH, 5, null); |
| } |
| |
| public static void setPlaySnapshotInterval(int delayInMilliseconds) { |
| IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID); |
| scope.putInt(PLAY_SNAPSHOT_DELAY_TIME, delayInMilliseconds); |
| try { |
| scope.flush(); |
| } catch (BackingStoreException e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| } |
| |
| public static int getPlaySnapshotInterval() { |
| return Platform.getPreferencesService().getInt(EDCDebugger.PLUGIN_ID, |
| PLAY_SNAPSHOT_DELAY_TIME, 5000, null); |
| } |
| |
| public static void setSnapshotCreationControl(String newSetting) { |
| IEclipsePreferences scope = EDCDebugger.getPrefs(EDCDebugger.PLUGIN_ID); |
| scope.put(PREF_CREATION_CONTROL, newSetting); |
| try { |
| scope.flush(); |
| } catch (BackingStoreException e) { |
| EDCDebugger.getMessageLogger().logError(null, e); |
| } |
| } |
| |
| public static String getSnapshotCreationControl() { |
| return Platform.getPreferencesService().getString(EDCDebugger.PLUGIN_ID, |
| PREF_CREATION_CONTROL, CREATE_MANUAL, null); |
| } |
| |
| protected static void playSnapshotSound() { |
| Bundle bundle = Platform.getBundle(EDCDebugger.getUniqueIdentifier()); |
| if (bundle == null) |
| return; |
| |
| URL url = null; |
| try { |
| url = FileLocator.toFileURL(bundle.getEntry(CAMERA_CLICK_WAV)); |
| } catch (IOException e) { |
| } catch (RuntimeException e){ |
| } |
| finally { |
| if (url != null){ |
| File f = new File(url.getFile()); |
| SnapshotUtils.playSoundFile(f); |
| } |
| } |
| |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getSnapshots() |
| */ |
| public List<Snapshot> getSnapshots() { |
| if (snapshotList == null || snapshotList.size() == 0) { |
| try { |
| loadAlbumMetada(false); |
| } catch (Exception e) { |
| EDCDebugger.getMessageLogger().logError("Failed to load snapshots", e); |
| } |
| } |
| |
| return snapshotList; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isLoaded() |
| */ |
| public boolean isLoaded() { |
| return loaded; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#getIndexOfSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot) |
| */ |
| public int getIndexOfSnapshot(Snapshot snap) { |
| return snapshotList.indexOf(snap); |
| } |
| |
| public void setCurrentSnapshotIndex(int index) { |
| if (currentSnapshotIndex >= 0 && currentSnapshotIndex < snapshotList.size()) { |
| currentSnapshotIndex = index; |
| } |
| } |
| |
| /** |
| * Update album.xml within the Album's .dsa file with new Snapshot data |
| * |
| * @param albumName |
| * - Name of album to display. Use null if value should not be |
| * updated. |
| * @param snap |
| * - Specific snapshot to update. Use null is snapshot should not |
| * be updated. |
| */ |
| public void updateSnapshotMetaData(String albumName, Snapshot snap) { |
| NodeList snapMetaDataNode = document.getElementsByTagName(METADATA); |
| |
| // try to update album display name |
| if (albumName != null) { |
| NodeList albumNameNode = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(ALBUM); |
| ((Element) albumNameNode.item(0)).setAttribute("albumName", albumName); |
| } |
| |
| // try to update snapshot data |
| if (snap != null) { |
| |
| NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT); |
| |
| int numSnapshots = elementSnapshots.getLength(); |
| for (int i = 0; i < numSnapshots; i++) { |
| Element currentSnapshotNode = (Element) elementSnapshots.item(i); |
| String fileName = currentSnapshotNode.getAttribute("fileName"); |
| if (fileName.equals(snap.getSnapshotFileName())) { |
| |
| currentSnapshotNode.setAttribute("description", snap.getSnapshotDescription()); |
| currentSnapshotNode.setAttribute("displayName", snap.getSnapshotDisplayName()); |
| |
| break; |
| } |
| } |
| } |
| |
| saveAlbumData(); |
| |
| // refresh all data |
| try { |
| loadAlbumMetada(true); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| |
| } |
| |
| private void saveAlbumData() { |
| try { |
| File tempFile = File.createTempFile("album", ".xml"); |
| File tempFile2 = new File(tempFile.getParent() + File.separator + ALBUM_DATA); |
| tempFile.delete(); |
| if (!tempFile2.exists()) { |
| tempFile2.delete(); |
| } |
| tempFile2.createNewFile(); |
| saveAlbum(new Path(tempFile2.toString())); |
| File[] fileList = { tempFile2 }; |
| ZipFileUtils.addFilesToZip(fileList, getLocation().toFile(), DSA_FILE_EXTENSIONS); |
| |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } catch (TransformerException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#deleteSnapshot(org.eclipse.cdt.debug.edc.internal.snapshot.Snapshot) |
| */ |
| public void deleteSnapshot(Snapshot snap) { |
| |
| NodeList snapMetaDataNode = document.getElementsByTagName(METADATA); |
| |
| NodeList elementSnapshotList = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT_LIST); |
| NodeList elementSnapshots = ((Element) snapMetaDataNode.item(0)).getElementsByTagName(SNAPSHOT); |
| |
| int numSnapshots = elementSnapshots.getLength(); |
| for (int i = 0; i < numSnapshots; i++) { |
| Element currentSnapshotNode = (Element) elementSnapshots.item(i); |
| String fileName = currentSnapshotNode.getAttribute("fileName"); |
| if (fileName.equals(snap.getSnapshotFileName())) { |
| elementSnapshotList.item(0).removeChild(currentSnapshotNode); |
| break; |
| } |
| } |
| |
| snapshotList.remove(snap); |
| |
| saveAlbumData(); |
| |
| // refresh all data |
| try { |
| loadAlbum(true); |
| loadAlbumMetada(true); |
| } catch (Exception e) { |
| |
| } |
| |
| ZipFileUtils.deleteFileFromZip(snap.getSnapshotFileName(), getLocation().toFile(), DSA_FILE_EXTENSIONS); |
| } |
| |
| @Override |
| public String toString() { |
| return "Album [name=" + name + ", launchName=" + launchName + ", sessionID=" + sessionID + "]"; |
| } |
| |
| public IPath createEmptyAlbum() { |
| IPath zipPath = null; |
| try { |
| zipPath = SnapshotUtils.getSnapshotsProject().getLocation(); |
| zipPath = zipPath.append(getDefaultAlbumName()); |
| zipPath = zipPath.addFileExtension("dsa"); |
| boolean created = ZipFileUtils.createNewZip(zipPath.toFile()); |
| |
| if (created && zipPath.toFile().exists()){ |
| setLocation(zipPath); |
| } else { |
| return null; |
| } |
| SnapshotUtils.getSnapshotsProject().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); |
| } catch (CoreException e) { |
| EDCDebugger.getMessageLogger().logError(e.getLocalizedMessage(), e); |
| } |
| return zipPath; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.edc.internal.snapshot.IAlbum#isRecording() |
| */ |
| public boolean isRecording() { |
| return recordingSessionID.length() > 0; |
| } |
| |
| /** |
| * @noreference This method is not intended to be referenced by clients. |
| */ |
| public static void addSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) { |
| listeners.add(listener); |
| } |
| |
| /** |
| * @noreference This method is not intended to be referenced by clients. |
| */ |
| public static void removeSnapshotAlbumEventListener(ISnapshotAlbumEventListener listener) { |
| listeners.remove(listener); |
| } |
| |
| public static void captureSnapshotForSession(final DsfSession session) { |
| Job createSnapshotJob = new Job("Creating Debug Snapshot") { |
| |
| @Override |
| protected IStatus run(final IProgressMonitor monitor) { |
| |
| Query<IFrameDMContext> frameQuery = new Query<IFrameDMContext>() { |
| @Override |
| protected void execute( |
| DataRequestMonitor<IFrameDMContext> rm) { |
| DsfServicesTracker servicesTracker = new DsfServicesTracker( |
| EDCDebugger.getBundleContext(), |
| session.getId()); |
| try { |
| RunControl runControl = servicesTracker.getService(RunControl.class); |
| IThreadDMContext[] suspendedThreads = runControl.getSuspendedThreads(); |
| if (suspendedThreads.length == 0) |
| { |
| rm.setData(null); |
| rm.done(); |
| } |
| else |
| { |
| Stack stackService = servicesTracker.getService(Stack.class); |
| if (stackService != null) { |
| stackService.getTopFrame(suspendedThreads[0], rm); |
| } |
| } |
| } finally { |
| servicesTracker.dispose(); |
| } |
| } |
| }; |
| |
| session.getExecutor().execute(frameQuery); |
| |
| IStatus status = Status.OK_STATUS; |
| try { |
| final StackFrameDMC stackFrame = (StackFrameDMC) frameQuery.get(); |
| |
| String sessionId = session.getId(); |
| Album album = Album.getRecordingForSession(sessionId); |
| if (album == null) { |
| album = new Album(); |
| album.setRecordingSessionID(sessionId); |
| } |
| final Album finalAlbum = album; |
| playSnapshotSound(); |
| |
| Query<IStatus> query = new Query<IStatus>() { |
| @Override |
| protected void execute(final DataRequestMonitor<IStatus> drm) { |
| try { |
| Snapshot newSnapshot = finalAlbum.createSnapshot(session, stackFrame, monitor); |
| // Fire the event to anyone listening |
| for (ISnapshotAlbumEventListener l : new ArrayList<ISnapshotAlbumEventListener>(listeners)) { |
| l.snapshotCreated(finalAlbum, newSnapshot, session, stackFrame); |
| } |
| drm.setData(Status.OK_STATUS); |
| } catch (Exception e) { |
| Status s = new Status(IStatus.ERROR, EDCDebugger.getUniqueIdentifier(), "Error creating snapshot.", e); |
| EDCDebugger.getMessageLogger().log(s); |
| drm.setStatus(s); |
| } |
| drm.done(); |
| } |
| }; |
| |
| session.getExecutor().execute(query); |
| |
| status = query.get(); |
| } catch (Exception e) { |
| status = new Status(Status.ERROR, EDCDebugger.PLUGIN_ID, "Error creating snapshot", e); |
| } |
| |
| return status; |
| } |
| }; |
| |
| createSnapshotJob.schedule(); |
| } |
| |
| public boolean isPlayingSnapshots() { |
| return playingSnapshots; |
| } |
| |
| public void setPlayingSnapshots(boolean playingSnapshots) { |
| this.playingSnapshots = playingSnapshots; |
| } |
| |
| public void stopPlayingSnapshots() { |
| setPlayingSnapshots(false); |
| openSnapshot(getCurrentSnapshotIndex()); // Reloading the current snapshot will resync the UI. |
| } |
| |
| } |