package hudson.plugins.kundo;
import hudson.tasks.Builder;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.model.Descriptor;
import hudson.model.Hudson;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.CopyOnWrite;
import hudson.util.ArgumentListBuilder;
import hudson.util.FormValidation;
import java.io.IOException;
import java.io.File;
import java.util.Map;
import java.util.HashMap;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.QueryParameter;
/**
* I have to recognise all the other Hudson Plugin developers
* without their source code I wouldn't have had any idea what
* was going on. Thanks for the inspiration, and in several
* places the code.
*/
public class Kundo extends Builder {
/**
* The phases, optional properties, and other Kundo options.
*/
private final String phases;
/**
* properties specified in the advanced section
*/
private final String properties;
/**
* Identifies {@link KundoInstallation} to be used.
*/
private final String kundoName;
@DataBoundConstructor
public Kundo( String phases, String properties, String kundoName ) {
this.phases = phases;
this.properties = properties;
this.kundoName = kundoName;
}
public String getProperties() {
return properties;
}
public String getPhases() {
return phases;
}
/**
* Gets the Kundo kernel to call,
* or null if only one installation exists.
*/
public KundoInstallation getKundo() {
for( KundoInstallation i : DESCRIPTOR.getInstallations() ) {
if( kundoName != null && i.getName().equals( kundoName ) )
return i;
}
return null;
}
public boolean perform( AbstractBuild<?,?> build, Launcher launcher, BuildListener listener ) throws IOException, InterruptedException {
ArgumentListBuilder args = new ArgumentListBuilder();
String execType;
if( launcher.isUnix() ){
execType = "kundo";
}else{
execType = "kundo.bat";
}
String normalizedPhases = phases.replaceAll( "[\t\r\n]+"," " );
String normalizedProperties = properties.replaceAll( "[\t\r\n]+"," " );
String[] splitProperties = normalizedProperties.split( " " );
HashMap propMap = new HashMap();
for( String property : splitProperties ){
if( property.indexOf( "=" ) != -1 ){
String[] splitProp = property.split( "=" );
if( splitProp.length == 2 ){
propMap.put( splitProp[0], splitProp[1] );
}
}
}
KundoInstallation currentInstall = getKundo();
if( currentInstall==null ) {
args.add( execType );
}else{
File exec = currentInstall.getExecutable();
if( !currentInstall.getExists() ) {
listener.fatalError( exec + " doesn't exist" );
return false;
}
args.add( exec.getPath() );
}
if( !propMap.isEmpty() ){
args.addKeyValuePairs( "-D", propMap );
}
args.addKeyValuePairs( "-D", build.getBuildVariables() );
args.addTokenized( normalizedPhases );
Map<String,String> env = build.getEnvironment(listener);
if( currentInstall != null )
env.put( "KUNDO_HOME", currentInstall.getKundoHome() );
if( !launcher.isUnix() ) {
args.prepend( "cmd.exe","/C" );
args.add( "&&", "exit", "%%ERRORLEVEL%%" );
}
try {
int r = launcher.launch().cmds(args).envs(env).stdout(listener).pwd(build.getModuleRoot()).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 Descriptor<Builder> {
@CopyOnWrite
private volatile KundoInstallation[] installations = new KundoInstallation[0];
private DescriptorImpl() {
super( Kundo.class );
load();
}
@Override
public String getHelpFile() {
return "/plugin/kundo/help.html";
}
public String getDisplayName() {
return "Invoke Kundo job";
}
public KundoInstallation[] getInstallations() {
return installations;
}
@Override
public boolean configure( StaplerRequest req, JSONObject formData ) {
installations = req.bindParametersToList( KundoInstallation.class, "kundo." ).toArray( new KundoInstallation[0] );
save();
return true;
}
/**
* Checks if the specified Hudson KUNDO_HOME is valid.
*/
public FormValidation doCheckKundoHome(@QueryParameter String value) {
if (!Hudson.getInstance().hasPermission(Hudson.ADMINISTER)) return FormValidation.ok();
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() && !new File( f, "conf" ).exists() && !new File( f, "groovy" ).exists() ) {
return FormValidation.error( f + " isn't a proper Kundo kernel" );
}
if( !new File( f, "bin/kundo" ).exists() ) {
return FormValidation.error( f + " isn't a proper Kundo kernel" );
}
return FormValidation.ok();
}
}
}