package com.github.guikeller.jettyrunner.model; import com.github.guikeller.jettyrunner.model.JettyRunnerConfiguration; import com.intellij.execution.ExecutionException; import com.intellij.execution.configurations.JavaCommandLineState; import com.intellij.execution.configurations.JavaParameters; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.util.PathUtil; import org.eclipse.jetty.runner.Runner; import org.jetbrains.annotations.NotNull; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * Jetty Runner Command Line - Runner Model - Holds the vars to Start / Execute Jetty * Visit - http://www.eclipse.org/jetty/documentation/current/runner.html * @see com.intellij.execution.configurations.JavaCommandLineState * @author Gui Keller */ public class JettyRunnerCommandLine extends JavaCommandLineState { // Jetty "Main Class" - the target (Jetty Runner) private static final String MAIN_CLASS = Runner.class.getName(); private ExecutionEnvironment environment; private JettyRunnerConfiguration model; public JettyRunnerCommandLine(@NotNull ExecutionEnvironment environment, JettyRunnerConfiguration model) { super(environment); this.environment = environment; this.model = model; } @Override public JavaParameters createJavaParameters() throws ExecutionException { JavaParameters javaParams = new JavaParameters(); // Use the same JDK as the project Project project = this.environment.getProject(); ProjectRootManager manager = ProjectRootManager.getInstance(project); javaParams.setJdk(manager.getProjectSdk()); // All modules to use the same things Module[] modules = ModuleManager.getInstance(project).getModules(); if (modules != null && modules.length > 0) { for (Module module : modules) { javaParams.configureByModule(module, JavaParameters.JDK_AND_CLASSES); } } // Dynamically adds the jetty-runner.jar to the classpath String jarPath = PathUtil.getJarPathForClass(Runner.class); javaParams.getClassPath().add(jarPath); javaParams.setMainClass(MAIN_CLASS); // Jetty XML - configured by the user String jettyXmls = this.getJettyXmlPaths(); if(jettyXmls != null) { javaParams.getProgramParametersList().addParametersString(jettyXmls); } // Port - configured by the user (default 8080) String port = this.getPort(); javaParams.getProgramParametersList().addParametersString(port); // Dynamic variables - working directory String basePath = project.getBasePath(); javaParams.setWorkingDirectory(basePath); // Path - configured by the user String path = this.getWebAppPath(); javaParams.getProgramParametersList().addParametersString(path); // Classes - configured by the user String classes = this.getClassesDirectory(); javaParams.getProgramParametersList().addParametersString(classes); // VM Args String vmArgs = this.getVmArgs(); if(vmArgs != null) { javaParams.getVMParametersList().addParametersString(vmArgs); } // Env Vars Map<String, String> environmentVariables = this.getEnvVars(); if(!environmentVariables.isEmpty()) { // The below should work, but does not boolean passParentEnvironmentVariables = this.isPassParentEnvironmentVariables(); javaParams.setupEnvs(environmentVariables, passParentEnvironmentVariables); // This is a workaround for the problem above.. Set<String> keys = environmentVariables.keySet(); for(String key : keys) { String value = environmentVariables.get(key); javaParams.getVMParametersList().addProperty(key, value); } } // All done, run it return javaParams; } // Helpers /** * Retrieves the "path" parameter * Jetty expects: /Path1 /path/to/WebApps * @return String value */ protected String getWebAppPath() { String paths = model.getWebappPaths(); String folders = model.getWebappFolders(); // Multiple values allowed - CSV String[] pathsArray = null; if(paths != null && !paths.isEmpty()){ pathsArray = paths.split(","); } // Multiple values allowed - CSV String[] foldersArray = null; if(folders != null && !folders.isEmpty()) { foldersArray = folders.split(","); } // Checking that we have paths and folders if( pathsArray != null && pathsArray.length > 0 && foldersArray != null && foldersArray.length >0 ){ // One path, one folder - two paths, two folders.. if(foldersArray.length != pathsArray.length){ throw new IllegalArgumentException("Incorrect folder(s) param: "+folders); } // Creates the 'path' parameter StringBuffer value = new StringBuffer(" --path "); for(int i=0; i<pathsArray.length; i++){ String path = pathsArray[i]; String folderPath = PathUtil.toPresentableUrl(foldersArray[i]); value.append(path).append(" ").append(folderPath).append(" "); } return value.toString(); } throw new IllegalArgumentException("Number of Path(s) and Folder(s) must match: "+paths+" / "+folders); } /** * Retrieves the "classes" parameter * @return String */ protected String getClassesDirectory() { String classesDirectories = model.getClassesDirectories(); // Multiple values allowed - CSV String[] classesFolders = null; if(classesDirectories != null && !classesDirectories.isEmpty()){ classesFolders = classesDirectories.split(","); } // Creates the 'classes' parameter if(classesFolders != null && classesFolders.length > 0){ StringBuffer value = new StringBuffer(" --classes "); for (String classesFolder : classesFolders){ value.append(PathUtil.toPresentableUrl(classesFolder)).append(" "); } return value.toString(); } throw new IllegalArgumentException("Invalid classes folder: "+classesDirectories); } /** * Retrieves the "config" parameter. * Using the specified jetty XML files * @return String */ protected String getJettyXmlPaths() { String xmls = model.getJettyXml(); // Multiple values allowed - CSV String[] xmlArray = null; if(xmls != null && !xmls.isEmpty()){ xmlArray = xmls.split(","); } // Creates the 'config' parameter if(xmlArray != null && xmlArray.length > 0){ StringBuffer value = new StringBuffer(" --config "); for (String jettyXml : xmlArray){ value.append(PathUtil.toPresentableUrl(jettyXml)).append(" "); } return value.toString(); } return null; } /** * Retrieves the "port" parameter * @return String */ protected String getPort() { String runningOnPort = model.getRunningOnPort(); //Single value - not optional if(runningOnPort != null && !runningOnPort.isEmpty()){ return " --port "+runningOnPort+" "; } throw new IllegalArgumentException("Invalid port: "+runningOnPort); } /** * Retrieves the "VM Args" parameter * @return String */ protected String getVmArgs() { String vmArgs = model.getVmArgs(); return vmArgs != null && !vmArgs.isEmpty() ? vmArgs : null; } /** * Retrieves the Env Vars * @return Map<String, String> */ protected Map<String, String> getEnvVars() { Map<String, String> environmentVariables = model.getEnvironmentVariables(); if(environmentVariables != null && !environmentVariables.isEmpty()) { return model.getEnvironmentVariables(); } return new HashMap<String, String>(0); } /** * Returns whether to pass through system / ide environment variables * @return boolean */ protected boolean isPassParentEnvironmentVariables() { return model.isPassParentEnvironmentVariables(); } public void setModel(JettyRunnerConfiguration model) { this.model = model; } }