package be.certipost.hudson.plugin;
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.model.Computer;
import hudson.model.Hudson;
import hudson.model.Node;
import hudson.model.Result;
import hudson.model.Hudson.MasterComputer;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.NodeProperty;
import hudson.slaves.NodePropertyDescriptor;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;
import hudson.util.CopyOnWriteList;
import hudson.util.DescribableList;
import hudson.util.FormValidation;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
/**
*
* @author Ramil Israfilov
*
*/
public final class SCPRepositoryPublisher extends Notifier {
/**
* Name of the scp site to post a file to.
*/
private String siteName;
public static final Logger LOGGER = Logger
.getLogger(SCPRepositoryPublisher.class.getName());
private final List<Entry> entries = new ArrayList<Entry>();
public SCPRepositoryPublisher() {
}
public SCPRepositoryPublisher(String siteName) {
if (siteName == null) {
// defaults to the first one
SCPSite[] sites = DESCRIPTOR.getSites();
if (sites.length > 0)
siteName = sites[0].getName();
}
this.siteName = siteName;
}
public List<Entry> getEntries() {
return entries;
}
public SCPSite getSite() {
SCPSite[] sites = DESCRIPTOR.getSites();
if (siteName == null && sites.length > 0)
// default
return sites[0];
for (SCPSite site : sites) {
if (site.getName().equals(siteName))
return site;
}
return null;
}
public BuildStepMonitor getRequiredMonitorService() {
return BuildStepMonitor.BUILD;
}
/**
* Returns the environment variables set for a node/slave. So you can use
* them, as are in your environment
*
* @param envVars
* @return
*/
public static EnvVars getEnvVars() {
DescribableList<NodeProperty<?>, NodePropertyDescriptor> nodeProperties = getNodeProperties();
// System.out.println(".getEnvVars()Computer.currentComputer() = "+Computer.currentComputer()+
// "nodeProperties = "+nodeProperties);
Iterator<NodeProperty<?>> iterator = nodeProperties.iterator();
while (iterator.hasNext()) {
NodeProperty<?> next = iterator.next();
// System.out.println(".getEnvVars()Computer.currentComputer() = "+Computer.currentComputer()+" next = "
// + next);
if (next instanceof EnvironmentVariablesNodeProperty) {
EnvironmentVariablesNodeProperty envVarProp = (EnvironmentVariablesNodeProperty) next;
EnvVars envVars = envVarProp.getEnvVars();
return envVars;
}
}
return null;
}
private static DescribableList<NodeProperty<?>, NodePropertyDescriptor> getNodeProperties() {
Node node = Computer.currentComputer().getNode();
DescribableList<NodeProperty<?>, NodePropertyDescriptor> nodeProperties = node
.getNodeProperties();
if (Computer.currentComputer() instanceof MasterComputer) {
Hudson instance = Hudson.getInstance();
nodeProperties = instance.getGlobalNodeProperties();
}
return nodeProperties;
}
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher,
BuildListener listener) throws InterruptedException, IOException {
if (build.getResult() == Result.FAILURE) {
// build failed. don't post
return true;
}
SCPSite scpsite = null;
PrintStream logger = listener.getLogger();
Session session = null;
ChannelSftp channel = null;
try {
scpsite = getSite();
if (scpsite == null) {
log(logger,
"No SCP site is configured. This is likely a configuration problem.");
build.setResult(Result.UNSTABLE);
return true;
}
log(logger, "Connecting to " + scpsite.getHostname());
session = scpsite.createSession(logger);
channel = scpsite.createChannel(logger, session);
Map<String, String> envVars = build.getEnvironment(listener);
// Patched for env vars
EnvVars objNodeEnvVars = getEnvVars();
if (objNodeEnvVars != null) {
envVars.putAll(objNodeEnvVars);
}
// ~ Patched for env vars
for (Entry e : entries) {
String expanded = Util.replaceMacro(e.sourceFile, envVars);
FilePath ws = build.getWorkspace();
FilePath[] src = ws.list(expanded);
if (src.length == 0) {
// try to do error diagnostics
log(logger, ("No file(s) found: " + expanded));
String error = ws.validateAntFileMask(expanded);
if (error != null)
log(logger, error);
continue;
}
String folderPath = Util.replaceMacro(e.filePath, envVars);
// Fix for recursive mkdirs
folderPath = folderPath.trim();
// Making workspace to have the same path separators like in the
// FilePath objects
String strWorkspacePath = ws.toString();
String strFirstFile = src[0].toString();
if (strFirstFile.indexOf('\\') >= 0) {
strWorkspacePath = strWorkspacePath.replace('/', '\\');
} else {
strWorkspacePath = strWorkspacePath.replace('\\', '/');// Linux
// Unix
}
// System.out
// .println("SCPRepositoryPublisher.perform()strWorkspacePath = "
// + strWorkspacePath);
envVars.put("strWorkspacePath", strWorkspacePath);
// ~Fix for recursive mkdirs
if (src.length == 1) {
// log(logger, "remote folderPath '" + folderPath
// + "',local file:'" + src[0].getName() + "'");
// System.out.println("remote folderPath '" + folderPath
// + "',local file:'" + src[0].getName() + "'");
scpsite
.upload(folderPath, src[0], envVars, logger,
channel);
} else {
for (FilePath s : src) {
// System.out.println("remote folderPath '" + folderPath
// + "',local file:'" + s.getName() + "'");
// log(logger, "remote folderPath '" + folderPath
// + "',local file:'" + s.getName() + "'");
scpsite.upload(folderPath, s, envVars, logger, channel);
}
}
}
} catch (IOException e) {
e.printStackTrace(listener.error("Failed to upload files"));
build.setResult(Result.UNSTABLE);
} catch (JSchException e) {
e.printStackTrace(listener.error("Failed to upload files"));
build.setResult(Result.UNSTABLE);
} catch (SftpException e) {
e.printStackTrace(listener.error("Failed to upload files"));
build.setResult(Result.UNSTABLE);
} finally {
if (scpsite != null) {
scpsite.closeSession(logger, session, channel);
}
}
return true;
}
@Override
public BuildStepDescriptor<Publisher> getDescriptor() {
return DESCRIPTOR;
}
@Extension
public static final DescriptorImpl DESCRIPTOR = new DescriptorImpl();
public static final class DescriptorImpl extends
BuildStepDescriptor<Publisher> {
public DescriptorImpl() {
super(SCPRepositoryPublisher.class);
load();
}
protected DescriptorImpl(Class<? extends Publisher> clazz) {
super(clazz);
}
private final CopyOnWriteList<SCPSite> sites = new CopyOnWriteList<SCPSite>();
public String getDisplayName() {
return "Publish artifacts to SCP Repository";
}
public String getShortName() {
return "[SCP] ";
}
@Override
public String getHelpFile() {
return "/plugin/scp/help.html";
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
return true;
}
@Override
public Publisher newInstance(StaplerRequest req, JSONObject formData) {
SCPRepositoryPublisher pub = new SCPRepositoryPublisher();
req.bindParameters(pub, "scp.");
pub.getEntries().addAll(
req.bindParametersToList(Entry.class, "scp.entry."));
return pub;
}
public SCPSite[] getSites() {
Iterator<SCPSite> it = sites.iterator();
int size = 0;
while (it.hasNext()) {
it.next();
size++;
}
return sites.toArray(new SCPSite[size]);
}
@Override
public boolean configure(StaplerRequest req, JSONObject formData) {
sites.replaceBy(req.bindParametersToList(SCPSite.class, "scp."));
save();
return true;
}
public FormValidation doKeyfileCheck(@QueryParameter String keyfile) {
keyfile = Util.fixEmpty(keyfile);
if (keyfile != null) {
File f = new File(keyfile);
if (!f.isFile()) {
return FormValidation.error("keyfile does not exist");
}
}
return FormValidation.ok();
}
public FormValidation doLoginCheck(StaplerRequest request) {
String hostname = Util.fixEmpty(request.getParameter("hostname"));
if (hostname == null) {// hosts is not entered yet
return FormValidation.ok();
}
SCPSite site = new SCPSite(hostname, request.getParameter("port"),
request.getParameter("user"), request.getParameter("pass"),
request.getParameter("keyfile"));
try {
try {
Session session = site.createSession(new PrintStream(
System.out));
site.closeSession(new PrintStream(System.out), session,
null);
} catch (JSchException e) {
LOGGER.log(Level.SEVERE, e.getMessage());
throw new IOException("Can't connect to server");
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getMessage());
return FormValidation.error(e.getMessage());
}
return FormValidation.ok();
}
}
public String getSiteName() {
return siteName;
}
public void setSiteName(String siteName) {
this.siteName = siteName;
};
protected void log(final PrintStream logger, final String message) {
logger.println(StringUtils.defaultString(DESCRIPTOR.getShortName())
+ message);
}
}