package fr.opensagres.mongodb.ide.launching.internal.jobs;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.osgi.util.NLS;
import fr.opensagres.mongodb.ide.core.IServerListener;
import fr.opensagres.mongodb.ide.core.ServerEvent;
import fr.opensagres.mongodb.ide.core.model.Server;
import fr.opensagres.mongodb.ide.core.model.ServerState;
import fr.opensagres.mongodb.ide.launching.internal.Activator;
import fr.opensagres.mongodb.ide.launching.internal.Messages;
import fr.opensagres.mongodb.ide.launching.internal.ProgressUtil;
import fr.opensagres.mongodb.ide.launching.internal.ServerLauncherManager;
import fr.opensagres.mongodb.ide.launching.internal.Trace;
public class StartJob extends ServerJob {
protected static final byte PUBLISH_NONE = 0;
protected static final byte PUBLISH_BEFORE = 1;
protected static final byte PUBLISH_AFTER = 2;
protected String launchMode;
public StartJob(Server server) {
super(server, NLS.bind(Messages.jobStarting, server.getName()));
setRule(server);
}
protected IStatus run(IProgressMonitor monitor) {
IStatus stat = startImpl(monitor);
return stat;
}
private IStatus startImpl(IProgressMonitor monitor) {
final boolean[] notified = new boolean[1];
monitor = ProgressUtil.getMonitorFor(monitor);
final Server server = getServer();
// add listener to the server
IServerListener listener = new IServerListener() {
public void serverChanged(ServerEvent event) {
int eventKind = event.getKind();
Server server = event.getServer();
if (eventKind == (ServerEvent.SERVER_CHANGE | ServerEvent.STATE_CHANGE)) {
ServerState state = server.getServerState();
if (state == ServerState.Started
|| state == ServerState.Stopped) {
// notify waiter
synchronized (notified) {
try {
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST,
"synchronousStart notify");
}
notified[0] = true;
notified.notifyAll();
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error notifying server start", e);
}
}
}
}
}
}
};
server.addServerListener(listener);
class Timer {
boolean timeout;
boolean alreadyDone;
}
final Timer timer = new Timer();
final int serverTimeout = 5000;
final IProgressMonitor monitor2 = monitor;
Thread thread = new Thread("Server Start Timeout") {
public void run() {
try {
int totalTimeout = serverTimeout;
if (totalTimeout < 0)
totalTimeout = 1;
boolean userCancelled = false;
int retryPeriod = 1000;
while (!notified[0] && totalTimeout > 0 && !userCancelled
&& !timer.alreadyDone) {
Thread.sleep(retryPeriod);
if (serverTimeout > 0)
totalTimeout -= retryPeriod;
if (!notified[0] && !timer.alreadyDone
&& monitor2.isCanceled()) {
// user canceled - set the server state to
// stopped
userCancelled = true;
ILaunch launch = getServer().getData(ILaunch.class);
if (launch != null && !launch.isTerminated())
launch.terminate();
// notify waiter
synchronized (notified) {
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST,
"synchronousStart user cancelled");
}
notified[0] = true;
notified.notifyAll();
}
}
}
if (!userCancelled && !timer.alreadyDone && !notified[0]) {
// notify waiter
synchronized (notified) {
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST,
"synchronousStart notify timeout");
}
if (!timer.alreadyDone && totalTimeout <= 0)
timer.timeout = true;
notified[0] = true;
notified.notifyAll();
}
}
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error notifying server start timeout", e);
}
}
}
};
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST, "synchronousStart 2");
}
// start the server
try {
startImpl2(launchMode, monitor);
thread.setDaemon(true);
thread.start();
} catch (CoreException e) {
server.removeServerListener(listener);
return e.getStatus();
}
if (monitor.isCanceled()) {
server.removeServerListener(listener);
timer.alreadyDone = true;
return Status.CANCEL_STATUS;
}
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST, "synchronousStart 3");
}
// wait for it! wait for it! ...
synchronized (notified) {
try {
while (!notified[0]
&& !monitor.isCanceled()
&& !timer.timeout
&& !(server.getServerState() == ServerState.Started || server
.getServerState() == ServerState.Stopped)) {
notified.wait();
}
} catch (Exception e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE,
"Error waiting for server start", e);
}
}
timer.alreadyDone = true;
}
server.removeServerListener(listener);
if (timer.timeout) {
// stop(false);
try {
ServerLauncherManager.stop(server, false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, NLS.bind(
Messages.errorStartTimeout, new String[] { getName(),
(serverTimeout / 1000) + "" }), null);
}
if (!monitor.isCanceled()
&& server.getServerState() == ServerState.Stopped)
return new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, NLS.bind(
Messages.errorStartFailed, getName()), null);
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST, "synchronousStart 4");
}
return Status.OK_STATUS;
}
private void startImpl2(String launchMode2, IProgressMonitor monitor)
throws CoreException {
Server server = getServer();
try {
ILaunchConfiguration launchConfig = ServerLauncherManager
.getLaunchConfiguration(server, true, monitor);
if (launchConfig != null) {
ILaunch launch = launchConfig.launch(ILaunchManager.RUN_MODE,
monitor); // , true); -
// causes
// workspace
// lock
server.setData(launch);
}
if (Trace.FINEST) {
Trace.trace(Trace.STRING_FINEST, "Launch: "
+ getServer().getData(ILaunch.class));
}
} catch (CoreException e) {
if (Trace.SEVERE) {
Trace.trace(Trace.STRING_SEVERE, "Error starting server "
+ server.toString(), e);
}
throw e;
}
}
}