package hudson.plugins.easyant; import hudson.CopyOnWrite; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import java.io.File; import java.io.IOException; import net.sf.json.JSONObject; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; /** * A builder for EasyAnt scripts * * @author Jean Louis Boudart */ public class EasyAnt extends Builder { private final String name; private final String targets; private final String buildFile; @DataBoundConstructor public EasyAnt(String name, String targets, String buildFile) { this.name = name; this.targets = targets; this.buildFile = buildFile; } /** * We'll use this from the <tt>config.jelly</tt>. */ public String getName() { return name; } public String getTargets() { return targets; } public String getBuildFile() { return buildFile; } public EasyAntInstallation getEasyAnt() { for (EasyAntInstallation i : DESCRIPTOR.getInstallations()) { if (name != null && i.getName().equals(name)) return i; } return null; } @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { ArgumentListBuilder args = new ArgumentListBuilder(); String execName; if (launcher.isUnix()) execName = "easyant"; else execName = "easyant.bat"; String normalizedTargets = targets.replaceAll("[\t\r\n]+", " "); EasyAntInstallation ai = getEasyAnt(); if (ai == null) { args.add(execName); } else { File exec = ai.getExecutable(); if (!ai.isAvailable()) { listener.fatalError(exec + " doesn't exist"); return false; } args.add(exec.getPath()); } args.addKeyValuePairs("-D", build.getBuildVariables()); args.addTokenized(normalizedTargets); EnvVars env = build.getEnvironment(listener); if (ai != null) env.put("EASYANT_HOME", ai.getEasyantHome()); if (!launcher.isUnix()) { // on Windows, executing batch file can't return the correct error // code, // so we need to wrap it into cmd.exe. // double %% is needed because we want ERRORLEVEL to be expanded // after // batch file executed, not before. This alone shows how broken // Windows is... args.prepend("cmd.exe", "/C"); args.add("&&", "exit", "%%ERRORLEVEL%%"); } FilePath rootLauncher = null; if (buildFile != null && buildFile.trim().length() != 0) { String rootBuildScriptReal = Util.replaceMacro(buildFile, env); rootLauncher = new FilePath(build.getModuleRoot(), new File( rootBuildScriptReal).getParent()); } else { rootLauncher = build.getModuleRoot(); } try { int r = launcher.launch().cmds(args).envs(env) .stdout(listener).pwd(rootLauncher).join(); return r == 0; } catch (IOException e) { Util.displayIOException(e, listener); e.printStackTrace(listener.fatalError("command execution failed")); return false; } } @Extension public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl(); public static final class DescriptorImpl extends BuildStepDescriptor<Builder> { @CopyOnWrite private volatile EasyAntInstallation[] installations = new EasyAntInstallation[0]; public DescriptorImpl() { load(); } public boolean isApplicable(Class<? extends AbstractProject> jobType) { return true; } protected DescriptorImpl(Class<? extends EasyAnt> clazz) { super(clazz); } @Override public String getHelpFile() { return "/plugin/easyant/help.html"; } public String getDisplayName() { return Messages.EasyAnt_DisplayName(); } public EasyAntInstallation[] getInstallations() { return installations; } @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { installations = req.bindJSONToList(EasyAntInstallation.class, json.get("inst")).toArray(new EasyAntInstallation[0]); save(); return true; } @Override public EasyAnt newInstance(StaplerRequest req, JSONObject formData) throws FormException { return (EasyAnt) req.bindJSON(clazz, formData); } /** * Checks if the specified Hudson EASYANT_HOME is valid. */ public FormValidation doCheckEasyAntHome(@QueryParameter String value) { File f = new File(Util.fixNull(value)); if (!f.isDirectory()) { return FormValidation.error(f + " is not a directory"); } if (!new File(f, "bin").exists() && !new File(f, "lib").exists()) { return FormValidation.error(f + " doesn't look like an EasyAnt directory"); } if (!new File(f, "bin/easyant").exists()) { return FormValidation.error(f + " doesn't look like an EasyAnt directory"); } return FormValidation.ok(); } } }