package be.certipost.hudson.plugin; import hudson.FilePath; import hudson.model.Computer; import hudson.model.Hudson; import hudson.model.Node; import hudson.model.Hudson.MasterComputer; import hudson.slaves.NodeProperty; import hudson.slaves.NodePropertyDescriptor; import hudson.util.DescribableList; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.util.Map; import java.util.logging.Logger; import org.apache.commons.lang.StringUtils; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import com.jcraft.jsch.SftpATTRS; import com.jcraft.jsch.SftpException; import com.jcraft.jsch.UserInfo; /** * * @author Ramil Israfilov * */ public class SCPSite { String hostname; int port; String username; String password; String keyfile; String rootRepositoryPath; public static final Logger LOGGER = Logger.getLogger(SCPSite.class .getName()); public SCPSite() { } public SCPSite(String hostname, int port, String username, String password, String rootRepositoryPath) { this.hostname = hostname; this.port = port; this.username = username; this.password = password; this.rootRepositoryPath = rootRepositoryPath.trim(); } public SCPSite(String hostname, String port, String username, String password) { this.hostname = hostname; try { this.port = Integer.parseInt(port); } catch (Exception e) { this.port = 22; } this.username = username; this.password = password; } public SCPSite(String hostname, String port, String username, String passphrase, String keyfile) { this(hostname, port, username, passphrase); this.keyfile = keyfile; } public String getKeyfile() { return keyfile; } public void setKeyfile(String keyfile) { this.keyfile = keyfile; } public String getHostname() { return hostname; } public void setHostname(String hostname) { this.hostname = hostname; } public String getPort() { return "" + port; } public void setPort(String port) { try { this.port = Integer.parseInt(port); } catch (Exception e) { this.port = 22; } } public int getIntegerPort() { return port; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRootRepositoryPath() { return rootRepositoryPath; } public void setRootRepositoryPath(String rootRepositoryPath) { this.rootRepositoryPath = rootRepositoryPath.trim(); } public String getName() { return hostname; } public Session createSession(PrintStream logger) throws JSchException { JSch jsch = new JSch(); Session session = jsch.getSession(username, hostname, port); if (this.keyfile != null && this.keyfile.length() > 0) { jsch.addIdentity(this.keyfile, this.password); } else { session.setPassword(password); } UserInfo ui = new SCPUserInfo(password); session.setUserInfo(ui); java.util.Properties config = new java.util.Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); return session; } public ChannelSftp createChannel(PrintStream logger, Session session) throws JSchException { ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); channel.setOutputStream(System.out); channel.connect(); return channel; } public void closeSession(PrintStream logger, Session session, ChannelSftp channel) { if (channel != null) { channel.disconnect(); channel = null; } if (session != null) { session.disconnect(); session = null; } } public void upload(String folderPath, FilePath filePath, Map<String, String> envVars, PrintStream logger, ChannelSftp channel) throws IOException, InterruptedException, SftpException { // if ( session == null || if (channel == null) { throw new IOException("Connection to " + hostname + ", user=" + username + " is not established"); } SftpATTRS rootdirstat = channel.stat(rootRepositoryPath); if (rootdirstat == null) { throw new IOException( "Can't get stat of root repository directory:" + rootRepositoryPath); } else { if (!rootdirstat.isDir()) { throw new IOException(rootRepositoryPath + " is not a directory"); } } if (filePath.isDirectory()) { FilePath[] subfiles = filePath.list("**/*"); if (subfiles != null) { for (int i = 0; i < subfiles.length; i++) { upload(folderPath + "/" + filePath.getName(), subfiles[i], envVars, logger, channel); } } } else { String localfilename = filePath.getName(); mkdirs(folderPath, logger, channel); // Fix for mkdirs String strWorkspacePath = envVars.get("strWorkspacePath"); String strRelativePath = extractRelativePath(strWorkspacePath, filePath, logger); String strTmp = concatDir(folderPath, strRelativePath); String strNewPath = concatDir(rootRepositoryPath, strTmp); if (!strRelativePath.equals("")) { // System.out.println("SCPSite.upload() mkdirs(strTmp = " // + strTmp); // Make subdirs mkdirs(strTmp, logger, channel); } if (!strNewPath.endsWith("/")) { strNewPath += "/"; } String strNewFilename = strNewPath + localfilename; log(logger, "uploading file: '" + strNewFilename + "'"); InputStream in = filePath.read(); channel.put(in, strNewFilename); // ~Fix for mkdirs in.close(); } } private void mkdirs(String filePath, PrintStream logger, ChannelSftp channel) throws SftpException, IOException { String pathnames[] = filePath.split("/"); String curdir = rootRepositoryPath; if (pathnames != null) { for (int i = 0; i < pathnames.length; i++) { if (pathnames[i].length() == 0) { continue; } SftpATTRS dirstat = null; try { dirstat = channel.stat(curdir + "/" + pathnames[i]); } catch (SftpException e) { if (e.getMessage() != null && e.getMessage().indexOf("No such file") == -1) { log(logger, "Error getting stat of directory:" + curdir + "/" + pathnames[i] + ":" + e.getMessage()); throw e; } } if (dirstat == null) { // try to create dir log(logger, "Trying to create " + curdir + "/" + pathnames[i]); channel.mkdir(curdir + "/" + pathnames[i]); } else { if (!dirstat.isDir()) { throw new IOException(curdir + "/" + pathnames[i] + " is not a directory:" + dirstat); } } curdir = curdir + "/" + pathnames[i]; } } } protected void log(final PrintStream logger, final String message) { logger .println(StringUtils .defaultString(SCPRepositoryPublisher.DESCRIPTOR .getShortName()) + message); } /** * @param folderPath * @param strRelativePath * @return */ private String concatDir(String folderPath, String strRelativePath) { String strTmp; if (folderPath.endsWith("/") || folderPath.equals("")) { strTmp = folderPath + strRelativePath; } else { strTmp = folderPath + "/" + strRelativePath; } // System.out.println("SCPSite.concatDir()strTmp = " + strTmp); return strTmp; } /** * Returns the relative path to the workspace * * @param strWorkspacePath * @param filePath * @return */ private String extractRelativePath(String strWorkspacePath, FilePath filePath, PrintStream logger) { String strRet = ""; String strFilePath = filePath.getParent().toString(); if (strWorkspacePath.length() == strFilePath.length()) { return ""; } if (strFilePath.length() > strWorkspacePath.length()) { strRet = strFilePath.substring(strWorkspacePath.length() + 1, strFilePath.length());// Exclude // first // file // separator } strRet = strRet.replace('\\', '/'); return strRet; } 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; } }