package com.dubture.composer.ui.job;
import java.io.IOException;
import javax.inject.Inject;
import org.apache.commons.exec.ExecuteException;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.pdtextensions.core.exception.ExecutableNotFoundException;
import org.pdtextensions.core.launch.ScriptLauncher;
import org.pdtextensions.core.launch.ScriptLauncherManager;
import org.pdtextensions.core.launch.ScriptNotFoundException;
import org.pdtextensions.core.launch.execution.ExecutionResponseAdapter;
import org.pdtextensions.core.ui.PEXUIPlugin;
import com.dubture.composer.core.ComposerPlugin;
import com.dubture.composer.core.launch.environment.ComposerEnvironmentFactory;
import com.dubture.composer.core.log.Logger;
import com.dubture.composer.ui.handler.ConsoleResponseHandler;
import com.dubture.composer.ui.job.runner.ComposerFailureMessageRunner;
import com.dubture.composer.ui.job.runner.MissingExecutableRunner;
abstract public class ComposerJob extends Job {
private IProject project;
private IProgressMonitor monitor;
private boolean cancelling = false;
private ScriptLauncher launcher;
@Inject
public ScriptLauncherManager manager;
protected static final IStatus ERROR_STATUS = new Status(Status.ERROR,
ComposerPlugin.ID,
"Error running composer, see log for details");
public ComposerJob(String name) {
super(name);
ContextInjectionFactory.inject(this, PEXUIPlugin.getDefault().getEclipseContext());
}
public ComposerJob(IProject project, String name) {
this(name);
this.setProject(project);
}
@Override
protected void canceling() {
if (cancelling || launcher == null || !monitor.isCanceled()) {
return;
}
launcher.abort();
monitor.done();
cancelling = true;
}
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
this.monitor = monitor;
try {
launcher = manager.getLauncher(ComposerEnvironmentFactory.FACTORY_ID, getProject());
} catch (ExecutableNotFoundException e) {
// inform the user of the missing executable
Display.getDefault().asyncExec(new MissingExecutableRunner());
return Status.OK_STATUS;
} catch (ScriptNotFoundException e) {
// run the downloader
Display.getDefault().asyncExec(new DownloadRunner());
return Status.OK_STATUS;
}
launcher.addResponseListener(new ConsoleResponseHandler());
launcher.addResponseListener(new ExecutionResponseAdapter() {
public void executionFailed(final String response, final Exception exception) {
Display.getDefault().asyncExec(new ComposerFailureMessageRunner(response, monitor));
}
@Override
public void executionMessage(String message) {
if (monitor != null && message != null) {
monitor.subTask(message);
monitor.worked(1);
}
}
});
monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
monitor.worked(1);
launch(launcher);
monitor.worked(1);
// refresh project
if (getProject() != null) {
getProject().refreshLocal(IProject.DEPTH_INFINITE, null);
monitor.worked(1);
}
} catch (Exception e) {
Logger.logException(e);
return ERROR_STATUS;
} finally {
monitor.done();
}
return Status.OK_STATUS;
}
abstract protected void launch(ScriptLauncher launcher) throws ExecuteException, IOException, InterruptedException;
public IProject getProject() {
return project;
}
public void setProject(IProject project) {
this.project = project;
}
private class DownloadRunner implements Runnable {
@Override
public void run() {
Shell shell = Display.getCurrent().getActiveShell();
if (shell == null) {
Logger.debug("Unable to get shell for message dialog.");
return;
}
if (MessageDialog.openConfirm(shell, "composer.phar not found", "composer.phar can not be found. Download it now?")) {
DownloadJob job = new DownloadJob(getProject());
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
// re-schedule the original job
ComposerJob.this.schedule();
}
});
job.setUser(true);
job.schedule();
}
}
}
}