/******************************************************************************* * Copyright (c) 2009 the CHISEL group and contributors. * 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: * the CHISEL group - initial API and implementation *******************************************************************************/ package ca.uvic.chisel.javasketch.launching; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.util.HashMap; import java.util.Properties; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.model.IStreamsProxy; import ca.uvic.chisel.javasketch.SketchPlugin; import ca.uvic.chisel.javasketch.launching.ui.FilterTab; /** * A trace client that is set up to store data in a local database. * @author Del Myers * */ public abstract class LocalDataBaseTraceClient implements ITraceClient { /** * */ public static final String PROCESS_PROPERTIES_FILE = "process.properties"; /** * */ public static final String ATTACH_TIME_PROPERTY = "time"; /** * */ public static final String HOST_PROPERTY = "host"; /** * */ public static final String PROCESS_PROPERTY = "process"; public static final String LABEL_PROPERTY = "label"; public static final String ID_PROPERTY = "id"; public static final String CONFIGURATION_FILE = "launch.configuration"; private String hostLabel; private ILaunchConfiguration configuration; private String id; private long attachTime; private String fileName; private ILaunch launch; private IPath storagePath; private HashMap<String, String> atts; private boolean paused; private String label; public LocalDataBaseTraceClient() { atts = new HashMap<String, String>(); } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#attach(org.eclipse.debug.core.ILaunch, org.eclipse.debug.core.ILaunchConfiguration, org.eclipse.core.runtime.IProgressMonitor) */ @Override public final void attach(ILaunch launch, ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException { this.launch = launch; this.configuration = configuration; this.attachTime = System.currentTimeMillis(); this.label = configuration.getName(); try { createProperties(); } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, SketchPlugin.PLUGIN_ID, "Unable to attach client ",e)); } doAttach(launch, configuration, monitor); DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { new DebugEvent(this, DebugEvent.CREATE) }); launch.addProcess(this); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IProcess#getLabel() */ @Override public String getLabel() { return "Tracing " + this.label; } protected abstract void doAttach(ILaunch launch, ILaunchConfiguration configuration, IProgressMonitor monitor) throws CoreException; /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#getAttachTime() */ @Override public long getAttachTime() { return attachTime; } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#getID() */ @Override public String getID() { if (this.id == null) { this.id = getLaunchConfiguration().getName() + "." + System.currentTimeMillis(); } return id; } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#getLaunchConfiguration() */ @Override public ILaunchConfiguration getLaunchConfiguration() { return configuration; } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#initialize(org.eclipse.debug.core.ILaunchConfiguration) */ @Override public final void initialize(ILaunchConfiguration configuration) throws CoreException { //this method will set up all the files that we need. this.configuration = configuration; this.paused = configuration.getAttribute(FilterTab.PAUSE_ON_START, true); getFileName(); doInitialize(configuration); } protected abstract void doInitialize(ILaunchConfiguration configuration) throws CoreException; /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#sendEvent(java.lang.Object) */ @Override public void sendEvent(Object event) throws IllegalArgumentException { } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#pauseTrace() */ @Override public final void pauseTrace() { performPauseRequest(); } protected abstract void performPauseRequest(); protected void handlePause() { paused = true; DebugEvent event =new DebugEvent(this, DebugEvent.MODEL_SPECIFIC, TRACE_PAUSED); DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] {event}); } /* (non-Javadoc) * @see ca.uvic.chisel.javasketch.launching.ITraceClient#resumeTrace() */ @Override public final boolean resumeTrace() { return performResumeRequest(); } protected abstract boolean performResumeRequest(); protected void handleResume() { paused = false; DebugEvent event =new DebugEvent(this, DebugEvent.MODEL_SPECIFIC, TRACE_RESUMED); DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] {event}); } @Override public boolean isPaused() { return paused; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IProcess#getAttribute(java.lang.String) */ @Override public String getAttribute(String key) { return atts.get(key); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IProcess#setAttribute(java.lang.String, java.lang.String) */ @Override public void setAttribute(String key, String value) { atts.put(key, value); } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IProcess#getLaunch() */ @Override public ILaunch getLaunch() { return launch; } /* (non-Javadoc) * @see org.eclipse.debug.core.model.IProcess#getStreamsProxy() */ @Override public IStreamsProxy getStreamsProxy() { return null; } /** * Gets the filename used to save the information that the server will * write to. * @return the filename to write to. * @throws CoreException */ protected String getFileName() throws CoreException { if (fileName != null) { return fileName; } IPath filePath = getStoragePath(); File projectFolder = new File(filePath.toOSString()); if (!projectFolder.exists()) { if (!projectFolder.mkdirs()) { throw new CoreException(new Status(Status.ERROR, SketchPlugin.PLUGIN_ID, "Unable to create location for trace files.")); } } String result = filePath.toOSString(); //convert escape characters result = result.replaceAll("\\\\", "\\\\\\\\"); this.fileName = result; return result; } /** * Returns the path in which data will be stored for this trace. * @return the path in which data will be stored for this trace. */ public IPath getStoragePath() throws CoreException { if (this.storagePath != null) { return storagePath; } IPath pluginState = SketchPlugin.getDefault().getStateLocation(); String configurationName = configuration.getName(); IPath configurationPath = pluginState.append(configurationName); IPath filePath = configurationPath.append(getID()); File file = new File(filePath.toOSString()); if (!file.exists()) { file.mkdirs(); } storagePath = filePath; return storagePath; } /** * Stores information about this launch for later reference in a standard Java properties * file. * @param projectFolder * @throws IOException * @throws CoreException */ private void createProperties() throws IOException, CoreException { IPath storagePath = getStoragePath(); File projectFolder = new File(storagePath.toOSString()); Properties props = new Properties(); props.put(PROCESS_PROPERTY, getLabel()); props.put(HOST_PROPERTY, getHostLabel()); props.put(LABEL_PROPERTY, getLabel()); props.put(ATTACH_TIME_PROPERTY, ""+getAttachTime()); props.put(ID_PROPERTY, getID()); File propertiesFile = new File(projectFolder, PROCESS_PROPERTIES_FILE); props.store(new FileOutputStream(propertiesFile), ""); //write out the launch configuration so that it can be loaded later File lcFile = new File(projectFolder, CONFIGURATION_FILE); String lcMemento = configuration.getMemento(); FileWriter writer = new FileWriter(lcFile); writer.write(lcMemento); writer.close(); } protected String getHostLabel() { return configuration.getName(); } /** * Cleans up the process so that it will display as terminated. */ protected void finish() { DebugPlugin manager= DebugPlugin.getDefault(); if (manager != null) { manager.fireDebugEventSet(new DebugEvent[]{new DebugEvent(this, DebugEvent.TERMINATE)}); } paused = false; } }