/*******************************************************************************
* Copyright (c) 2012 Pivotal Software, Inc.
* All rights reserved. This program and the accompanying materials
* are 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:
* Pivotal Software, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.commands;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.grails.ide.eclipse.core.GrailsCoreActivator;
import org.grails.ide.eclipse.core.launch.GrailsCommandLaunchConfigurationDelegate;
import org.grails.ide.eclipse.core.launch.GrailsLaunchArgumentUtils;
import org.grails.ide.eclipse.core.launch.SynchLaunch;
import org.grails.ide.eclipse.core.launch.SynchLaunch.ILaunchResult;
import org.grails.ide.eclipse.core.model.GrailsVersion;
import org.grails.ide.eclipse.core.model.IGrailsInstall;
import org.grails.ide.eclipse.longrunning.LongRunningProcessGrailsExecutor;
/**
* An instance of this class provides some way of executing Grails commands.
* <p>
* Default implementation provided here is using the "old" mechanism that creates special
* launch configuration for the grails command and launches it. A single command is executed
* per launch.
* <p>
* An alternative implementation is found in {@link LongRunningProcessGrailsExecutor}
*
* @author Kris De Volder
* @since 2.5.3
*/
public class GrailsExecutor {
protected static GrailsExecutor DEFAULT_INSTANCE = new GrailsExecutor();
private static Map<GrailsVersion, GrailsExecutor> instances = new HashMap<GrailsVersion, GrailsExecutor>();
// The code that is commented out below, related to listener is used by run on server tests which are currently disabled.
// When those tests are re-enabled we may need this code back, and it will then need some work, since it
// assumes only a single executor is exists... but we now have a map of executors per grails version.
// /**
// * At present this only used for testing purposes, to monitor whether the expected commands get executed, and if
// * they produce the expected results.
// */
// public static GrailsExecutorListener listener = null;
//
// public static synchronized void setListener(GrailsExecutorListener newListener) {
// shutDownIfNeeded(); // Force new executor creation to ensure listener will be installed in it.
// listener = newListener;
// }
public static synchronized GrailsExecutor getInstance(GrailsVersion version) {
GrailsExecutor instance = instances.get(version);
if (instance==null) {
boolean keepRunning = GrailsCoreActivator.getDefault().getKeepRunning();
if (keepRunning && LongRunningProcessGrailsExecutor.canHandleVersion(version)) {
instance = LongRunningProcessGrailsExecutor.INSTANCE;
} else {
instance = new GrailsExecutor();
}
instances.put(version, instance);
}
// if (listener!=null) {
// //copy listener to local, final variable used by the instance. Don't want to have access
// //listener variable, which is mutable, outside of this synchronized method.
// final GrailsExecutorListener wrappedListener = listener;
// final GrailsExecutor wrapped = instance;
// instance = new GrailsExecutor() {
// public ILaunchResult synchExec(GrailsCommand cmd) throws CoreException {
// try {
// ILaunchResult result = wrapped.synchExec(cmd);
// wrappedListener.commandExecuted(cmd, result);
// return result;
// } catch (CoreException e) {
// wrappedListener.commandExecuted(cmd, e);
// throw e;
// } catch (RuntimeException e) {
// wrappedListener.commandExecuted(cmd, e);
// throw e;
// }
// }
// public void shutDown() {
// wrapped.shutDown();
// }
// };
// }
return instance;
}
// private static boolean canHandleVersion(GrailsExecutor instance, GrailsVersion version) {
// if (instance instanceof LongRunningProcessGrailsExecutor) {
// return LongRunningProcessGrailsExecutor.canHandleVersion(version);
// }
// return true; // default executor handles all versions.
// }
public ILaunchResult synchExec(GrailsCommand cmd) throws CoreException {
try {
IGrailsInstall grailsHome = cmd.getGrailsInstall();
if (grailsHome == null) {
throw new CoreException(
new Status(
IStatus.ERROR,
GrailsCoreActivator.PLUGIN_ID,
"The Grails installation directory has not been configured or is invalid.\n"
+ "Check the Grails project or workspace preference page."));
}
ILaunchConfigurationWorkingCopy launchConf = GrailsCommandLaunchConfigurationDelegate.getLaunchConfiguration(grailsHome, cmd.getProject(), cmd.getCommand(), cmd.getPath());
String buildListener = cmd.getBuildListener();
if (buildListener!=null) {
GrailsLaunchArgumentUtils.setGrailsBuildListener(launchConf, buildListener);
}
Map<String, String> systemProperties = cmd.getSystemProperties();
if (systemProperties!=null) {
GrailsLaunchArgumentUtils.setSystemProperties(launchConf, systemProperties);
}
SynchLaunch synchLaunch = new SynchLaunch(launchConf, cmd.getGrailsCommandTimeOut(), GrailsCoreActivator.getDefault().getGrailsCommandOutputLimit());
synchLaunch.setShowOutput(cmd.isShowOutput());
ILaunchResult launchResult = synchLaunch.synchExec();
if (launchResult.getStatus().isOK()) {
cmd.runPostOp();
}
return launchResult;
} catch (CoreException e) {
throw e;
} catch (Throwable e) {
throw new CoreException(new Status(IStatus.ERROR, GrailsCoreActivator.PLUGIN_ID, "Problem executing grails command", e));
}
}
/**
* A GrailsExecutor may have some "stuff" it needs to cleanup when it is deactivated. This method performs the
* cleanup. Default implementation does nothing.
*/
public void shutDown() {
}
public static synchronized void shutDownIfNeeded() {
Iterator<GrailsVersion> versions = instances.keySet().iterator();
while (versions.hasNext()) {
GrailsVersion version = versions.next();
GrailsExecutor instance = instances.get(version);
instance.shutDown();
versions.remove();
}
}
}