package com.github.jarlakxen.scala.sbt; import java.io.File; import java.net.URI; import java.net.URL; import java.util.Arrays; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.IStreamListener; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IStreamMonitor; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.launching.IRuntimeClasspathEntry; import org.eclipse.jdt.launching.JavaRuntime; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import com.github.jarlakxen.scala.sbt.util.UIUtil; /** * * @author Naoki Takezoe */ public class SbtExecutor { private IProject project; private File workDir; /** * Constructor. * * @param project the target project */ public SbtExecutor(IProject project){ this.project = project; } public void setWorkDirectory(File workDir){ this.workDir = workDir; } /** * Executes the given SBT command. * <p> * This method creates Run Configuration for execution of SBT command automatically. * And execution results are displayed in the Console view. * * @param command the SBT command * @param terminate whether terminate the process if the project definition is invalid */ public ILaunch execute(String command, boolean terminate){ if(project == null){ return null; } SbtProjectConfiguration projectConfig = new SbtProjectConfiguration(project); try { ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType type = manager.getLaunchConfigurationType( IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); // Creates new configuration ILaunchConfigurationWorkingCopy wc = null; if(command == null || command.length() == 0){ wc = type.newInstance(null, String.format("sbt - %s", project.getName())); } else { wc = type.newInstance(null, String.format("sbt %s - %s", command, project.getName())); } // Sets the project name wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); // Sets the main class wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "xsbt.boot.Boot"); // Sets the VM arguments wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, createVMarguments(projectConfig)); // Sets the working directory if it's specified if(this.workDir != null){ wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, workDir.getAbsolutePath()); } // Sets the classpath File jarFile = projectConfig.getProjectSbtRuntime(); URL sbtRuntimeUrl = null; if(jarFile != null){ sbtRuntimeUrl = jarFile.toURI().toURL(); } if(sbtRuntimeUrl == null){ UIUtil.showErrorDialog("Can't find SBT runtime in your project."); return null; } IRuntimeClasspathEntry entry = JavaRuntime.newArchiveRuntimeClasspathEntry(new Path(sbtRuntimeUrl.getPath())); wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, Arrays.asList(entry.getMemento())); wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false); // Sets the command wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, command); // Saves the created configuration ILaunchConfiguration launchConfig = wc.doSave(); // Runs the process using the created configuration ILaunch launch = launchConfig.launch(ILaunchManager.RUN_MODE, null); final IProcess process = launch.getProcesses()[0]; if(terminate){ process.getStreamsProxy().getOutputStreamMonitor().addListener(new IStreamListener() { @Override public void streamAppended(String message, IStreamMonitor monitor) { if(message.trim().endsWith("(r)etry, (q)uit, (l)ast, or (i)gnore?")){ try { process.terminate(); } catch(Exception ex){ } } } }); } return launch; } catch(Exception ex){ SbtPlugin.logException(ex); } return null; } private static class ProxyConfig { public String host = null; public int port = -1; public String userId = null; public String password = null; public ProxyConfig(IProxyService proxyService, URI uri){ IProxyData[] proxyDataForHost = proxyService.select(uri); for (IProxyData data : proxyDataForHost) { if (data.getHost() != null) { host = data.getHost(); port = data.getPort(); userId = data.getUserId(); password = data.getPassword(); } } } } private static String createVMarguments(SbtProjectConfiguration projectConfig){ try { BundleContext context = SbtPlugin.getDefault().getBundle().getBundleContext(); ServiceReference<IProxyService> ref = context.getServiceReference(IProxyService.class); IProxyService proxyService = context.getService(ref); ProxyConfig httpProxyConfig = new ProxyConfig(proxyService, new URI("http://www.google.co.jp/")); ProxyConfig httpsProxyConfig = new ProxyConfig(proxyService, new URI("https://www.google.co.jp/")); StringBuilder sb = new StringBuilder(); sb.append("-Djline.WindowsTerminal.directConsole=false "); // http proxy if(httpProxyConfig.host != null){ sb.append("-Dhttp.proxyHost=").append(httpProxyConfig.host).append(" "); } if(httpProxyConfig.port >= 0){ sb.append("-Dhttp.proxyPort=").append(httpProxyConfig.port).append(" "); } if(httpProxyConfig.userId != null){ sb.append("-Dhttp.proxyUser=").append(httpProxyConfig.userId).append(" "); } if(httpProxyConfig.password != null){ sb.append("-Dhttp.proxyPassword=").append(httpProxyConfig.password).append(" "); } // https proxy if(httpsProxyConfig.host != null){ sb.append("-Dhttps.proxyHost=").append(httpsProxyConfig.host).append(" "); } if(httpsProxyConfig.port >= 0){ sb.append("-Dhttps.proxyPort=").append(httpsProxyConfig.port).append(" "); } if(httpsProxyConfig.userId != null){ sb.append("-Dhttps.proxyUser=").append(httpsProxyConfig.userId).append(" "); } if(httpsProxyConfig.password != null){ sb.append("-Dhttps.proxyPassword=").append(httpsProxyConfig.password).append(" "); } return sb.toString(); } catch(Exception ex) { SbtPlugin.logException(ex); return ""; } } }