package io.jenkins.plugins.sample; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.*; import hudson.model.*; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.tools.ToolInstallation; import hudson.util.ArgumentListBuilder; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.Arrays; public class PBAutoBuildBuilder extends Builder implements SimpleBuildStep { /** * GUI fields */ private String pbAutoBuildName; private String cmdLineArgs; private boolean continueOnBuildFailure; private boolean unstableIfWarnings; /** * When this builder is created in the project configuration step, the * builder object will be created from the strings below. * * @param pbAutoBuildName * The PowerBuilder logical name * @param cmdLineArgs * Whitespace separated list of command line arguments for pb autobuild utility * @param continueOnBuildFailure * If true, job will continue despite pb autobuild build failure * @param unstableIfWarnings * If true, job will be unstable if there are warnings */ @DataBoundConstructor public PBAutoBuildBuilder(String pbAutoBuildName, String cmdLineArgs, boolean continueOnBuildFailure, boolean unstableIfWarnings) { this.pbAutoBuildName = pbAutoBuildName; this.cmdLineArgs = cmdLineArgs; this.continueOnBuildFailure = continueOnBuildFailure; this.unstableIfWarnings = unstableIfWarnings; } public String getPbAutoBuildName() { return pbAutoBuildName; } @DataBoundSetter public void setPbAutoBuildName(String pbAutoBuildName) { this.pbAutoBuildName = pbAutoBuildName; } public String getCmdLineArgs() { return cmdLineArgs; } @DataBoundSetter public void setCmdLineArgs(String cmdLineArgs) { this.cmdLineArgs = cmdLineArgs; } public boolean isContinueOnBuildFailure() { return continueOnBuildFailure; } @DataBoundSetter public void setContinueOnBuildFailure(boolean continueOnBuildFailure) { this.continueOnBuildFailure = continueOnBuildFailure; } public boolean isUnstableIfWarnings() { return unstableIfWarnings; } @DataBoundSetter public void setUnstableIfWarnings(boolean unstableIfWarnings) { this.unstableIfWarnings = unstableIfWarnings; } public PBAutoBuildInstallation getPBAutoBuild() { DescriptorImpl descriptor = (DescriptorImpl) getDescriptor(); for (PBAutoBuildInstallation i : descriptor.getInstallations()) { if (pbAutoBuildName != null && i.getName().equals(pbAutoBuildName)) return i; } if ( descriptor.getInstallations().length == 1 ) { return descriptor.getInstallations()[0]; } return null; } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { return runPBAutoBuild(build, build.getWorkspace(), launcher, listener); } @Override public void perform(@NonNull Run run, @NonNull FilePath workspace, @NonNull EnvVars env, @NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException, IOException { runPBAutoBuild(run, workspace, launcher, listener); } public boolean runPBAutoBuild(Run build, @NonNull FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { ArgumentListBuilder args = new ArgumentListBuilder(); PBAutoBuildInstallation ai = getPBAutoBuild(); String execName = "pbautobuild220.exe"; if (ai == null) { listener.fatalError("Unable to find a valid installation"); } else { EnvVars env = build.getEnvironment(listener); //Node node = Computer.currentComputer().getNode(); //if (node != null) { //ai = ai.forNode(node, listener); ai = ai.forEnvironment(env); String pathToPBAutoBuild = getToolFullPath(launcher, ai.getHome(), execName); FilePath exec = new FilePath(launcher.getChannel(), pathToPBAutoBuild); try { if (!exec.exists()) { listener.fatalError(pathToPBAutoBuild + " doesn't exist"); return false; } } catch (IOException e) { listener.fatalError("Failed checking for existence of " + pathToPBAutoBuild); return false; } listener.getLogger().println("Path to PB AutoBuild utility: " + pathToPBAutoBuild); args.add(pathToPBAutoBuild); if (ai.getDefaultArgs() != null) { args.add(tokenizeArgs(ai.getDefaultArgs())); } //} } EnvVars env = build.getEnvironment(listener); String normalizedArgs = cmdLineArgs.replaceAll("[\t\r\n]+", " "); normalizedArgs = Util.replaceMacro(normalizedArgs, env); //normalizedArgs = Util.replaceMacro(normalizedArgs, build.getBuildVariables()); if (!normalizedArgs.trim().isEmpty()) args.add(tokenizeArgs(normalizedArgs)); if (!launcher.isUnix()) { final int cpi = getCodePageIdentifier(build.getCharset()); if (cpi != 0) args.prepend("cmd.exe", "/C", "\"", "chcp", String.valueOf(cpi), "&&"); else args.prepend("cmd.exe", "/C", "\""); args.add("\"", "&&", "exit", "%%ERRORLEVEL%%"); } try { listener.getLogger() .println(String.format("Executing the command %s from %s", args.toStringWithQuote(), workspace)); // Parser to find the number of Warnings/Errors PBAutoBuildConsoleParser mbcp = new PBAutoBuildConsoleParser(listener.getLogger(), build.getCharset()); PBAutoBuildConsoleAnnotator annotator = new PBAutoBuildConsoleAnnotator(listener.getLogger(), build.getCharset(), false); // Launch the pbautobuild utility int r = launcher.launch().cmds(args).envs(env).stdout(mbcp).stdout(annotator).pwd(workspace).join(); // Check the number of warnings if (unstableIfWarnings && mbcp.getNumberOfWarnings() > 0) { listener.getLogger().println("> Set build UNSTABLE because there are warnings."); build.setResult(Result.UNSTABLE); } // Return the result of the compilation return continueOnBuildFailure || (r == 0); } catch (IOException e) { Util.displayIOException(e, listener); build.setResult(Result.FAILURE); return false; } } /** * Get the full path of the tool to run. If given path is a directory, this * will append the executable name. */ static String getToolFullPath(Launcher launcher, String pathToTool, String execName) throws IOException, InterruptedException { String fullPath = pathToTool; FilePath exec = new FilePath(launcher.getChannel(), fullPath); if (exec.isDirectory()) { if (!fullPath.endsWith("\\")) { fullPath = fullPath + "\\"; } fullPath = fullPath + execName; } return fullPath; } @Override public Descriptor getDescriptor() { return super.getDescriptor(); } /** * Tokenize a set of arguments, preserving quotes. * * @param args * @return */ static String[] tokenizeArgs(String args) { if (args == null) { return null; } final String[] tokenize = Util.tokenize(args); if (args.endsWith("\\")) { tokenize[tokenize.length - 1] = tokenize[tokenize.length - 1] + "\\"; } return tokenize; } @Extension @Symbol("pbautobuild") public static final class DescriptorImpl extends BuildStepDescriptor { @CopyOnWrite private volatile PBAutoBuildInstallation[] installations = new PBAutoBuildInstallation[0]; public DescriptorImpl() { super(PBAutoBuildBuilder.class); load(); } @Override public String getDisplayName() { return Messages.PBAutoBuildBuilder_DisplayName(); } @SuppressWarnings("rawtypes") @Override public boolean isApplicable(Class jobType) { return true; } public PBAutoBuildInstallation[] getInstallations() { return Arrays.copyOf(installations, installations.length); } public void setInstallations(PBAutoBuildInstallation... antInstallations) { this.installations = antInstallations; save(); } public PBAutoBuildInstallation.DescriptorImpl getToolDescriptor() { return ToolInstallation.all().get(PBAutoBuildInstallation.DescriptorImpl.class); } } private static int getCodePageIdentifier(Charset charset) { final String s_charset = charset.name(); if (s_charset.equalsIgnoreCase("utf-8")) // Unicode return 65001; else if (s_charset.equalsIgnoreCase("ibm437")) // US return 437; else if (s_charset.equalsIgnoreCase("ibm850")) // OEM Multilingual Latin // 1 return 850; else if (s_charset.equalsIgnoreCase("ibm852")) // OEM Latin2 return 852; else if (s_charset.equalsIgnoreCase("shift_jis") || s_charset.equalsIgnoreCase("windows-31j")) // Japanese return 932; else if (s_charset.equalsIgnoreCase("us-ascii")) // US-ASCII return 20127; else if (s_charset.equalsIgnoreCase("euc-jp")) // Japanese return 20932; else if (s_charset.equalsIgnoreCase("iso-8859-1")) // Latin 1 return 28591; else if (s_charset.equalsIgnoreCase("iso-8859-2")) // Latin 2 return 28592; else if (s_charset.equalsIgnoreCase("IBM00858")) return 858; else if (s_charset.equalsIgnoreCase("IBM775")) return 775; else if (s_charset.equalsIgnoreCase("IBM855")) return 855; else if (s_charset.equalsIgnoreCase("IBM857")) return 857; else if (s_charset.equalsIgnoreCase("ISO-8859-4")) return 28594; else if (s_charset.equalsIgnoreCase("ISO-8859-5")) return 28595; else if (s_charset.equalsIgnoreCase("ISO-8859-7")) return 28597; else if (s_charset.equalsIgnoreCase("ISO-8859-9")) return 28599; else if (s_charset.equalsIgnoreCase("ISO-8859-13")) return 28603; else if (s_charset.equalsIgnoreCase("ISO-8859-15")) return 28605; else if (s_charset.equalsIgnoreCase("KOI8-R")) return 20866; else if (s_charset.equalsIgnoreCase("KOI8-U")) return 21866; else if (s_charset.equalsIgnoreCase("UTF-16")) return 1200; else if (s_charset.equalsIgnoreCase("UTF-32")) return 12000; else if (s_charset.equalsIgnoreCase("UTF-32BE")) return 12001; else if (s_charset.equalsIgnoreCase("windows-1250")) return 1250; else if (s_charset.equalsIgnoreCase("windows-1251")) return 1251; else if (s_charset.equalsIgnoreCase("windows-1252")) return 1252; else if (s_charset.equalsIgnoreCase("windows-1253")) return 1253; else if (s_charset.equalsIgnoreCase("windows-1254")) return 1254; else if (s_charset.equalsIgnoreCase("windows-1257")) return 1257; else if (s_charset.equalsIgnoreCase("Big5")) return 950; else if (s_charset.equalsIgnoreCase("EUC-KR")) return 51949; else if (s_charset.equalsIgnoreCase("GB18030")) return 54936; else if (s_charset.equalsIgnoreCase("GB2312")) return 936; else if (s_charset.equalsIgnoreCase("IBM-Thai")) return 20838; else if (s_charset.equalsIgnoreCase("IBM01140")) return 1140; else if (s_charset.equalsIgnoreCase("IBM01141")) return 1141; else if (s_charset.equalsIgnoreCase("IBM01142")) return 1142; else if (s_charset.equalsIgnoreCase("IBM01143")) return 1143; else if (s_charset.equalsIgnoreCase("IBM01144")) return 1144; else if (s_charset.equalsIgnoreCase("IBM01145")) return 1145; else if (s_charset.equalsIgnoreCase("IBM01146")) return 1146; else if (s_charset.equalsIgnoreCase("IBM01147")) return 1147; else if (s_charset.equalsIgnoreCase("IBM01148")) return 1148; else if (s_charset.equalsIgnoreCase("IBM01149")) return 1149; else if (s_charset.equalsIgnoreCase("IBM037")) return 37; else if (s_charset.equalsIgnoreCase("IBM1026")) return 1026; else if (s_charset.equalsIgnoreCase("IBM273")) return 20273; else if (s_charset.equalsIgnoreCase("IBM277")) return 20277; else if (s_charset.equalsIgnoreCase("IBM278")) return 20278; else if (s_charset.equalsIgnoreCase("IBM280")) return 20280; else if (s_charset.equalsIgnoreCase("IBM284")) return 20284; else if (s_charset.equalsIgnoreCase("IBM285")) return 20285; else if (s_charset.equalsIgnoreCase("IBM297")) return 20297; else if (s_charset.equalsIgnoreCase("IBM420")) return 20420; else if (s_charset.equalsIgnoreCase("IBM424")) return 20424; else if (s_charset.equalsIgnoreCase("IBM500")) return 500; else if (s_charset.equalsIgnoreCase("IBM860")) return 860; else if (s_charset.equalsIgnoreCase("IBM861")) return 861; else if (s_charset.equalsIgnoreCase("IBM863")) return 863; else if (s_charset.equalsIgnoreCase("IBM864")) return 864; else if (s_charset.equalsIgnoreCase("IBM865")) return 865; else if (s_charset.equalsIgnoreCase("IBM869")) return 869; else if (s_charset.equalsIgnoreCase("IBM870")) return 870; else if (s_charset.equalsIgnoreCase("IBM871")) return 20871; else if (s_charset.equalsIgnoreCase("ISO-2022-JP")) return 50220; else if (s_charset.equalsIgnoreCase("ISO-2022-KR")) return 50225; else if (s_charset.equalsIgnoreCase("ISO-8859-3")) return 28593; else if (s_charset.equalsIgnoreCase("ISO-8859-6")) return 28596; else if (s_charset.equalsIgnoreCase("ISO-8859-8")) return 28598; else if (s_charset.equalsIgnoreCase("windows-1255")) return 1255; else if (s_charset.equalsIgnoreCase("windows-1256")) return 1256; else if (s_charset.equalsIgnoreCase("windows-1258")) return 1258; else return 0; } }