/*******************************************************************************
* 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.runtime;
import static org.jboss.tools.windup.runtime.WindupRuntimePlugin.logError;
import static org.jboss.tools.windup.runtime.WindupRuntimePlugin.logInfo;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteException;
import org.apache.commons.exec.ExecuteResultHandler;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.LogOutputStream;
import org.apache.commons.exec.PumpStreamHandler;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.e4.core.di.annotations.Creatable;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.jboss.windup.tooling.ExecutionBuilder;
@Singleton
@Creatable
public class WindupRmiClient {
/**
* Server status
*/
public static final String WINDUP_SERVER_STATUS = "windup/server/status"; //$NON-NLS-1$
private ExecuteWatchdog watchdog;
private ExecutionBuilder executionBuilder;
@Inject private IEventBroker eventBroker;
private IEclipsePreferences defaultPreferences = DefaultScope.INSTANCE.getNode(WindupRuntimePlugin.PLUGIN_ID);
private IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(WindupRuntimePlugin.PLUGIN_ID);
public Path getWindupHome() {
String path = preferences.get(IPreferenceConstants.WINDUP_HOME, "");
if (path.isEmpty()) {
path = defaultPreferences.get(IPreferenceConstants.WINDUP_HOME, "");
}
if (path.isEmpty()) {
path = WindupRuntimePlugin.getDefaultWindupHome();
}
return new File(path).toPath();
}
public int getRmiPort() {
int port = preferences.getInt(IPreferenceConstants.RMI_PORT, -1);
if (port == -1) {
port = defaultPreferences.getInt(IPreferenceConstants.RMI_PORT, -1);
}
if (port == -1) {
port = IPreferenceConstants.DEFAULT_RMI_PORT;
}
return port;
}
public void startWindup(final IProgressMonitor monitor) {
logInfo("Begin start RHAMT."); //$NON-NLS-1$
monitor.worked(1);
CommandLine cmdLine = CommandLine.parse(getWindupHome().toString());
cmdLine.addArgument("--startServer"); //$NON-NLS-1$
cmdLine.addArgument(String.valueOf(getRmiPort()));
watchdog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
ExecuteResultHandler handler = new ExecuteResultHandler() {
@Override
public void onProcessFailed(ExecuteException e) {
logInfo("onProcessFailed"); //$NON-NLS-1$
executionBuilder = null;
notifyServerChanged();
}
@Override
public void onProcessComplete(int exitValue) {
logInfo("onProcessComplete"); //$NON-NLS-1$
executionBuilder = null;
notifyServerChanged();
}
};
DefaultExecutor executor = new DefaultExecutor();
executor.setStreamHandler(new PumpStreamHandler(new LogOutputStream() {
@Override
protected void processLine(String line, int logLevel) {
logInfo("Message from RHAMT executor: " + line); //$NON-NLS-1$
monitor.worked(1);
}
}));
executor.setWatchdog(watchdog);
executor.setExitValue(1);
monitor.worked(1);
try {
logInfo("Starting RHAMT in server mode..."); //$NON-NLS-1$
executor.execute(cmdLine, null, handler);
} catch (IOException e) {
WindupRuntimePlugin.log(e);
}
}
public boolean isWindupServerRunning() {
return executionBuilder != null;
}
/**
* @return true if the ExecutionBuilder is not null, false otherwise.
*/
public boolean updateWindupServer() {
if (isWindupServerRunning()) {
return true;
}
else {
this.executionBuilder = WindupRmiClient.getExecutionBuilder(getRmiPort());
notifyServerChanged();
return executionBuilder != null;
}
}
private void notifyServerChanged() {
eventBroker.post(WINDUP_SERVER_STATUS, executionBuilder);
}
public ExecutionBuilder getExecutionBuilder() {
return executionBuilder;
}
public String getWindupVersion() {
String version = "unknown";
try {
version = executionBuilder.getVersion();
} catch (RemoteException e) {
logInfo("Issue while attempting to retrieve RHAMT server version."); //$NON-NLS-1$
}
return version;
}
private static ExecutionBuilder getExecutionBuilder(int rmiPort) {
logInfo("Attempting to retrieve ExecutionBuilder from registry."); //$NON-NLS-1$
try {
Registry registry = LocateRegistry.getRegistry(rmiPort);
ExecutionBuilder executionBuilder = (ExecutionBuilder) registry.lookup(ExecutionBuilder.LOOKUP_NAME);
executionBuilder.clear();
logInfo("ExecutionBuilder retrieved from registry."); //$NON-NLS-1$
return executionBuilder;
} catch (RemoteException e) {
logError("Error while attempting to retrieve the ExecutionBuilder from RMI registry.", e); //$NON-NLS-1$
} catch (NotBoundException e) {
logError("ExecutionBuilder not yet bound.", e); //$NON-NLS-1$
}
return null;
}
@PreDestroy
public void shutdownWindup() {
ExecutionBuilder builder = WindupRmiClient.getExecutionBuilder(getRmiPort());
if (builder != null) {
try {
logInfo("ExecutionBuilder found in RMI Registry. Attempting to terminate it."); //$NON-NLS-1$
builder.terminate();
if (executionBuilder != null && executionBuilder != builder) {
logInfo("Attempting to terminate it current reference to ExecutionBuilder."); //$NON-NLS-1$
executionBuilder.terminate();
}
} catch (RemoteException e) {
logError("Error while terminating a previous RHAMT server instance.", e); //$NON-NLS-1$
}
}
executionBuilder = null;
notifyServerChanged();
}
}