/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.windup.ui.util;
import java.io.File;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
import javax.inject.Singleton;
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.di.annotations.Creatable;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.jboss.tools.windup.runtime.WindupRmiClient;
import org.jboss.tools.windup.ui.WindupUIPlugin;
import org.jboss.tools.windup.ui.internal.Messages;
import org.jboss.tools.windup.ui.util.FutureUtils.AbstractDelegatingMonitorJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
@Creatable
public class WindupLauncher {
private static Logger logger = LoggerFactory.getLogger(WindupLauncher.class);
// TODO: Move to preference item.
public static final long WINDUP_START_DURATION_TIMEOUT = 45000;
public static final long WINDUP_STOP_DURATION_TIMEOUT = 35000;
@Inject private WindupRmiClient windupClient;
public void shutdown(WinupServerCallback callback) {
Display.getDefault().syncExec(() -> {
Job job = new Job(Messages.WindupShuttingDown) {
@Override
protected IStatus run(IProgressMonitor monitor) {
IStatus result = Status.OK_STATUS;
try {
monitor.beginTask(Messages.WindupShuttingDown, 3);
shutdown(monitor);
} catch (ExecutionException | TimeoutException | InterruptedException e) {
WindupUIPlugin.log(e);
result = new Status(IStatus.ERROR, WindupUIPlugin.PLUGIN_ID, e.getMessage(), e);
} finally {
monitor.done();
}
if (monitor.isCanceled()) {
result = Status.CANCEL_STATUS;
}
return result;
}
};
job.setUser(true);
job.addJobChangeListener(new JobChangeAdapter() {
public void done(IJobChangeEvent event) {
callback.serverShutdown(event.getResult());
}
});
job.schedule();
});
}
private void shutdown(IProgressMonitor monitor) throws InterruptedException, ExecutionException, TimeoutException {
logger.info("Shutting Windup down."); //$NON-NLS-1$
monitor.worked(1);
windupClient.shutdownWindup();
monitor.worked(1);
Future<IStatus> future = WindupLauncher.getTerminateWindupFuture(windupClient);
FutureUtils.waitForFuture(WINDUP_STOP_DURATION_TIMEOUT, future, monitor);
monitor.worked(1);
}
public static Future<IStatus> getTerminateWindupFuture(WindupRmiClient windupClient) {
return new Future<IStatus>() {
private AtomicBoolean cancelled = new AtomicBoolean(false);
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
cancelled.set(true);
return true;
}
@Override
public boolean isCancelled() {
return cancelled.get();
}
@Override
public boolean isDone() {
return !windupClient.isWindupServerRunning();
}
@Override
public IStatus get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public IStatus get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
};
}
public void start(WinupServerCallback callback) {
Display.getDefault().syncExec(() -> {
logger.info("Start Windup Server."); //$NON-NLS-1$
String windupHome = windupClient.getWindupHome().toString();
boolean executable = new File(windupHome).setExecutable(true);
if (!executable) {
logger.info("Windup not executable."); //$NON-NLS-1$
callback.windupNotExecutable();
return;
}
Job job = createStartWindupJob();
IStatus status = FutureUtils.runWithProgress(job, WINDUP_START_DURATION_TIMEOUT, 5, callback.getShell(),
Messages.WindupStartingDetail);
callback.serverStart(status);
});
}
public Job createStartWindupJob() {
Job job = new AbstractDelegatingMonitorJob(Messages.WindupStartingTitle) {
@Override
protected IStatus doRun(IProgressMonitor monitor) {
Future<IStatus> future = new Future<IStatus>() {
private AtomicBoolean cancelled = new AtomicBoolean(false);
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
cancelled.set(true);
return true;
}
@Override
public boolean isCancelled() {
return cancelled.get();
}
@Override
public boolean isDone() {
return windupClient.updateWindupServer();
}
@Override
public IStatus get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public IStatus get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
};
try {
monitor.subTask(Messages.WindupRunStartScipt);
windupClient.startWindup(monitor);
FutureUtils.waitForFuture(WINDUP_START_DURATION_TIMEOUT, future, monitor);
} catch (ExecutionException | TimeoutException | InterruptedException e) {
WindupUIPlugin.log(e);
} finally {
monitor.done();
}
monitor.done();
return Status.OK_STATUS;
}
};
job.setUser(true);
return job;
}
public static interface WinupServerCallback {
void serverShutdown(IStatus status);
void serverStart(IStatus status);
void windupNotExecutable();
Shell getShell();
}
}