/* * The MIT License * * Copyright (c) 2010, Gregory Covert Smith * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.plugins.staf; import hudson.EnvVars; import hudson.Extension; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Computer; import hudson.model.Descriptor.FormException; import hudson.model.Hudson; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.tools.ToolInstallation; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.VariableResolver; import java.io.IOException; import java.util.Map; import net.sf.json.JSONObject; import org.jvnet.localizer.ResourceBundleHolder; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; /** * Defines the STAF build step */ public class STAF extends Builder { /** Identifies {@link STAFInstallation} to be used. */ private final String stafInstallationName; /** * The target endpoint */ private final String endpoint; /** * The target service */ private final String service; /** * The request */ private final String request; @DataBoundConstructor public STAF(String stafInstallationName, String endpoint, String service, String request) { this.stafInstallationName = stafInstallationName; if(endpoint.length() != 0) { this.endpoint = endpoint; } else { this.endpoint = "local"; } this.service = service; this.request = request; } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } /** * Returns the {@link STAFInstallation} to use when the build takes place * ({@code null} if none has been set). */ public STAFInstallation getStafInstallation() { for (STAFInstallation installation : getDescriptor().getInstallations()) { if (getStafInstallationName() != null && installation.getName().equals(getStafInstallationName())) { return installation; } } return null; } public String getStafInstallationName() { return stafInstallationName; } public String getEndpoint() { return endpoint; } public String getService() { return service; } public String getRequest() { return request; } @Override public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { AbstractProject project = build.getProject(); ArgumentListBuilder args = new ArgumentListBuilder(); EnvVars env = build.getEnvironment(listener); VariableResolver<String> varResolver = build.getBuildVariableResolver(); // --- STAF installation --- // has a STAF installation been set? STAFInstallation stafInstallation = getStafInstallation(); if (stafInstallation == null) { listener.fatalError(ResourceBundleHolder.get(STAF.class).format("NoInstallationSet")); return false; } stafInstallation = stafInstallation.forNode(Computer.currentComputer().getNode(), listener); stafInstallation = stafInstallation.forEnvironment(env); String stafExecutable = stafInstallation.getStafExecutable(launcher); if (stafExecutable == null) { listener.fatalError(ResourceBundleHolder.get(STAF.class).format("NoStafExecutable", stafInstallation.getName())); return false; } // add all of the required paramaters for the installation to the env Map<String, String> stafEnv = stafInstallation.getRequiredEnvVars(); env.overrideAll(stafEnv); args.add(stafExecutable); // add the endpoint args.add(getEndpoint()); // add the service name args.add(getService()); // add all of the request parameters String lRequests = Util.replaceMacro(env.expand(getRequest()), varResolver); args.addTokenized(lRequests.replaceAll("[\t\r\n]+", " ")); try { int r = launcher.launch().cmds(args).envs(env).stdout(listener).pwd(build.getWorkspace()).join(); if(r != 0) { // handle some known cases for bad error codes to log appropriately String errorMessage; switch (r){ // more should be added. If there are definite ones to add... case(21): errorMessage = ResourceBundleHolder.get(STAF.class).format("StafServiceNotRunning", r); default: errorMessage = ResourceBundleHolder.get(STAF.class).format("ExecutionResultNotZero", r); } listener.fatalError(errorMessage); return false; } else { return true; } } catch (IOException ioe) { Util.displayIOException(ioe, listener); String errorMessage = ResourceBundleHolder.get(STAF.class).format("ExecutionFailed"); listener.fatalError(errorMessage); return false; } } @Extension public static class DescriptorImpl extends BuildStepDescriptor<Builder> { public DescriptorImpl() { load(); } protected DescriptorImpl(Class<? extends STAF> clazz) { super(clazz); } @Override public String getDisplayName() { return ResourceBundleHolder.get(STAF.class).format("DisplayName"); } public STAFInstallation[] getInstallations() { return Hudson.getInstance().getDescriptorByType(STAFInstallation.DescriptorImpl.class).getInstallations(); } /** * Returns the {@link STAFInstallation.DescriptorImpl} instance. */ public STAFInstallation.DescriptorImpl getToolDescriptor() { return ToolInstallation.all().get(STAFInstallation.DescriptorImpl.class); } /** * Checks for fields */ public FormValidation doCheckService(@QueryParameter String value) { if (value.equals("")) { return FormValidation.error(ResourceBundleHolder.get(STAF.class).format("ServiceCannotBeEmpty", value)); } return FormValidation.ok(); } @Override public boolean isApplicable(Class<? extends AbstractProject> jobType) { return true; } @Override public Builder newInstance(StaplerRequest req, JSONObject formData) throws FormException { return req.bindJSON(STAF.class, formData); } } }