/*
* Created on Jun 14, 2007 Copyright (C) 2001-5, Anthony Harrison anh23@pitt.edu
* (jactr.org) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version. This library is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details. You should have
* received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jactr.eclipse.runtime.launching.session;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.UUID;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IDebugTarget;
import org.jactr.eclipse.runtime.RuntimePlugin;
import org.jactr.eclipse.runtime.debug.ACTRDebugTarget;
import org.jactr.eclipse.runtime.launching.ACTRLaunchConfigurationUtils;
import org.jactr.eclipse.runtime.session.ISession;
import org.jactr.eclipse.runtime.session.manager.internal.SessionManager;
import org.jactr.tools.async.credentials.ICredentials;
public abstract class AbstractSession
{
protected ILaunch _launch;
protected ILaunchConfiguration _configuration;
protected Job _sessionJob;
private IPath _relativeWorkingDirectory;
private IPath _absoluteWorkingDirectory;
protected volatile boolean _isRunning = false;
protected boolean _wasStopped = false;
protected boolean _destroyed = false;
private Date _executionStart;
private IJobChangeListener _listener;
private final UUID _id;
private ISession _newSession;
public AbstractSession(ILaunch launch, ILaunchConfiguration configuration)
{
_id = UUID.randomUUID();
_launch = launch;
_configuration = configuration;
_listener = new IJobChangeListener() {
public void aboutToRun(IJobChangeEvent event)
{
_isRunning = true;
// RuntimePlugin.info("Starting " + event.getJob().getName());
}
public void awake(IJobChangeEvent event)
{
// TODO Auto-generated method stub
}
@SuppressWarnings("unchecked")
public void done(IJobChangeEvent event)
{
_isRunning = false;
boolean wasNormal = event.getResult().getSeverity() == IStatus.OK;
// RuntimePlugin.info("Completed " + event.getJob().getName() +
// " normal:"
// + wasNormal + " terminated:" + _launch.isTerminated());
try
{
/*
* if something went wrong, force the termination
*/
if (!wasNormal && !_launch.isTerminated())
{
for (IDebugTarget target : _launch.getDebugTargets())
try
{
if (target.isSuspended() && target.canResume())
target.resume();
if (target.canTerminate() && !target.isTerminated())
target.terminate();
}
catch (Exception e)
{
RuntimePlugin.error("Could not resume " + target.getName(), e);
}
_launch.terminate();
}
}
catch (DebugException e1)
{
RuntimePlugin.getDefault().getLog().log(e1.getStatus());
}
/**
* otherwise disconnect cleanly. this should wait until the otherside
* has disconnected.
*/
try
{
disconnect(!wasNormal);
// RuntimePlugin.info("Disconnected wasNormal: " + wasNormal);
}
catch (Exception e)
{
RuntimePlugin.error(e.getMessage(), e);
}
if (wasNormal)
getSessionTracker().remove(AbstractSession.this, wasNormal);
else
getSessionTracker().cancel(AbstractSession.this);
try
{
IProject project = ACTRLaunchConfigurationUtils
.getProject(_configuration);
if (_relativeWorkingDirectory != null && project != null)
{
IFolder folder = project.getFolder(_relativeWorkingDirectory);
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
}
}
catch (CoreException ce)
{
}
_sessionJob = null;
}
public void running(IJobChangeEvent event)
{
}
@SuppressWarnings("unchecked")
public void scheduled(IJobChangeEvent event)
{
getSessionTracker().add(AbstractSession.this);
((SessionManager) RuntimePlugin.getDefault().getSessionManager())
.addSession(AbstractSession.this);
}
public void sleeping(IJobChangeEvent event)
{
}
};
}
/**
* short term hack to bridge the two systems
*
* @return
*/
public ISession getSession()
{
return _newSession;
}
/**
* short term hack to bridge the two systems
*
* @param session
*/
public void setSession(ISession session)
{
_newSession = session;
}
public UUID getId()
{
return _id;
}
public ILaunch getLaunch()
{
return _launch;
}
public ILaunchConfiguration getConfiguration()
{
return _configuration;
}
public void setRelativeWorkingDirectory(IPath path)
{
_relativeWorkingDirectory = path;
}
/**
* project relative working directory
*
* @return
*/
public IPath getRelativeWorkingDirectory()
{
return _relativeWorkingDirectory;
}
public void setAbsoluteWorkingDirectory(IPath path)
{
_absoluteWorkingDirectory = path;
}
/**
* project relative working directory
*
* @return
*/
public IPath getAbsoluteWorkingDirectory()
{
return _absoluteWorkingDirectory;
}
/**
* destroy the session and signal. This is called by the client, typically
* when all inspections have been done. However, it is not guaranteed to be
* called at all.
*/
public void destroy()
{
if (isDestroyed()) return;
if (isActive())
throw new IllegalStateException("Cannot destroy active sessions");
_destroyed = true;
if (_configuration != null) try
{
_configuration.delete();
}
catch (Exception e)
{
}
finally
{
_configuration = null;
}
getSessionTracker().destroy(this);
}
public boolean isDestroyed()
{
return _destroyed;
}
abstract protected SessionTracker getSessionTracker();
abstract public InetSocketAddress getConnectionAddress();
abstract public ICredentials getCredentials();
abstract protected Job createSessionJob();
abstract protected void connect() throws CoreException;
/**
* disconnect will be called after the job completes
*
* @param force
* @throws CoreException
*/
abstract protected void disconnect(boolean force) throws CoreException;
public Date getExecutionStartTime()
{
return _executionStart;
}
public void start() throws CoreException
{
_executionStart = new Date();
_sessionJob = createSessionJob();
_sessionJob.addJobChangeListener(_listener);
connect();
_sessionJob.schedule();
}
public boolean isActive()
{
return _isRunning && !_wasStopped;
}
public boolean isDebugSession()
{
for (IDebugTarget debugger : _launch.getDebugTargets())
if (debugger instanceof ACTRDebugTarget) return true;
return false;
}
public ACTRDebugTarget getACTRDebugTarget()
{
for (IDebugTarget debugger : _launch.getDebugTargets())
if (debugger instanceof ACTRDebugTarget)
return (ACTRDebugTarget) debugger;
return null;
}
/**
* force the termination of the session
*/
public void stop() throws CoreException
{
_wasStopped = true;
if (_sessionJob != null) _sessionJob.cancel();
}
}