package hudson.plugins.perforce;
import hudson.CopyOnWrite;
import hudson.EnvVars;
import hudson.Extension;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.EnvironmentSpecific;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.TaskListener;
import hudson.slaves.NodeSpecific;
import hudson.tools.ToolDescriptor;
import hudson.tools.ToolInstallation;
import hudson.tools.ToolProperty;
import hudson.util.FormValidation;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import javax.servlet.ServletException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Information about Perforce installation. This includes the path to p4 executable.
*
*/
public final class PerforceToolInstallation extends ToolInstallation implements NodeSpecific<PerforceToolInstallation>, EnvironmentSpecific<PerforceToolInstallation> {
//To store migrated data as all the tool installations are created on one go.
static transient ArrayList<PerforceToolInstallation> p4Tools = new ArrayList<PerforceToolInstallation>();
/**
* Default constructor.
*
* @param name Installation name
* @param home Path to p4.exe
* @param properties Additional tool installation data
*/
@DataBoundConstructor
public PerforceToolInstallation(String name, String home, List<? extends ToolProperty<?>> properties) {
super(name, home, properties);
}
/**
* Get the path to p4.exe
*
* @return Path to p4.exe
*/
public String getP4Exe() {
return getHome();
}
/**
* Migrate old data into new tool installations if needed.
*/
@Initializer(after=InitMilestone.JOB_LOADED)
public static void onLoaded() {
DescriptorImpl descriptor = (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
PerforceToolInstallation[] installations = getInstallations(descriptor);
//Allow only one migration round. Old "p4Exe" field is kept in job configuration until the job is saved.
if (installations.length > 0) {
return;
}
if (!p4Tools.isEmpty()) {
Hudson.getInstance().getDescriptorByType(DescriptorImpl.class).setInstallations(p4Tools.toArray(new PerforceToolInstallation[p4Tools.size()]));
}
}
private static PerforceToolInstallation[] getInstallations(DescriptorImpl descriptor) {
PerforceToolInstallation[] installations;
try {
installations = descriptor.getInstallations();
} catch (NullPointerException e) {
installations = new PerforceToolInstallation[0];
}
return installations;
}
/**
* Migrate data from old job specific "p4Exe" field. Create a tool installation for each
* individual path with the path as the tool name.
*
* @param exe The path to p4 executable
*/
public static synchronized void migrateOldData(String exe) {
for (PerforceToolInstallation tool : p4Tools) {
//Tool installation already exists, Unix case
if (File.separatorChar == '/' && tool.getName().equals(exe)) {
return;
}
//Tool installation already exists, Windows case
if (File.separatorChar != '/' && tool.getName().equalsIgnoreCase(exe)) {
return;
}
}
p4Tools.add(new PerforceToolInstallation(exe, exe, Collections.<ToolProperty<?>>emptyList()));
}
public PerforceToolInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException {
return new PerforceToolInstallation(getName(), translateFor(node, log), Collections.<ToolProperty<?>>emptyList());
}
public PerforceToolInstallation forEnvironment(EnvVars environment) {
return new PerforceToolInstallation(getName(), environment.expand(getHome()), Collections.<ToolProperty<?>>emptyList());
}
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl) Hudson.getInstance().getDescriptor(PerforceToolInstallation.class);
}
@Extension
public static class DescriptorImpl extends ToolDescriptor<PerforceToolInstallation> {
@CopyOnWrite
private volatile PerforceToolInstallation[] installations = new PerforceToolInstallation[0];
public DescriptorImpl() {
super();
load();
}
@Override
public String getDisplayName() {
return "Perforce";
}
@Override
public boolean configure(StaplerRequest req, JSONObject json) throws FormException {
super.configure(req, json);
save();
return true;
}
@Override
public PerforceToolInstallation[] getInstallations() {
return installations;
}
@Override
public void setInstallations(PerforceToolInstallation... installations) {
this.installations = installations;
save();
}
/**
* Checks if the path to p4 executable exists.
*/
public FormValidation doCheckHome(@QueryParameter File value)
throws IOException, ServletException {
Hudson.getInstance().checkPermission(Hudson.ADMINISTER);
String path = value.getPath();
return FormValidation.validateExecutable(path);
}
}
}