X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.support.simple%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fjsch%2FScpTo.java;h=07f428c4df03de90537fdf8bd5d97881fe665ee0;hb=c9672b7c16ee662ff452fff8405a67cac091a15e;hp=d10125fe77005431ac8b8d2f35e186d0a053fe3c;hpb=e7ddf0b3a271a2f22108ee5b9fba69888f5c78ec;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java index d10125fe7..07f428c4d 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java @@ -1,14 +1,22 @@ package org.argeo.slc.jsch; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.springframework.core.io.Resource; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; +import org.springframework.util.StringUtils; import com.jcraft.jsch.Channel; import com.jcraft.jsch.ChannelExec; @@ -17,15 +25,112 @@ import com.jcraft.jsch.Session; public class ScpTo extends AbstractJschTask { private final static Log log = LogFactory.getLog(ScpTo.class); - private Resource localFile; - private String remoteFile; + private Resource localResource; + private String remotePath; - public void run() { + private String dir; + private String remoteDir; + private List includes = new ArrayList(); + + private List excludes = new ArrayList(); + + private PathMatcher pathMatcher; + + public void run(Session session) { + if (StringUtils.hasText(dir)) { + if (!StringUtils.hasText(remoteDir)) + throw new SlcException("Remote dir has to be specified."); + + String dirOs = dir.replace('/', File.separatorChar); + if (dirOs.charAt(dir.length() - 1) != File.separatorChar) { + dirOs = dirOs + File.separator; + } + + if (pathMatcher == null) + pathMatcher = new AntPathMatcher(); + + log.info("Start multiple scp based on " + dirOs); + scanDir(session, dirOs, "", includes, excludes); + } + + if (localResource != null) { + try { + File lFile = localResource.getFile(); + uploadFile(session, lFile, remotePath); + } catch (IOException e) { + OutputStream out = null; + InputStream in = null; + File tempFile = null; + try { + tempFile = File.createTempFile(getClass().getSimpleName() + + "-" + localResource.getFilename(), null); + out = FileUtils.openOutputStream(tempFile); + in = localResource.getInputStream(); + IOUtils.copy(in, out); + uploadFile(session, tempFile, remotePath); + } catch (IOException e1) { + throw new SlcException("Can neither interpret resource " + + localResource + + " as file, nor create a temporary file", e1); + } finally { + IOUtils.closeQuietly(in); + IOUtils.closeQuietly(out); + FileUtils.deleteQuietly(tempFile); + } + } + } + } + + protected void scanDir(Session session, String dir, String currentRelPath, + List includes, List excludes) { + File[] files = new File(dir).listFiles(); + for (File file : files) { + if (!file.isDirectory()) { + String relPath = currentRelPath.concat(file.getName()); + if (match(relPath, includes, excludes, false)) { + uploadFile(session, file, remoteDir + '/' + relPath); + } + } else { + String relPath = currentRelPath.concat(file.getName()).concat( + "/"); + if (match(relPath, includes, excludes, true)) { + String nextDir = dir.concat(file.getName()).concat( + File.separator); + scanDir(session, nextDir, relPath, includes, excludes); + } + } + } + } + + protected Boolean match(String path, List includes, + List excludes, boolean matchStart) { + for (String patternIn : includes) { + boolean matchIn = matchStart ? pathMatcher.matchStart(patternIn, + path) : pathMatcher.match(patternIn, path); + if (matchIn) { + // Could be included, check excludes + boolean excluded = false; + ex: for (String patternEx : excludes) { + boolean matchEx = matchStart ? pathMatcher.matchStart( + patternEx, path) : pathMatcher.match(patternEx, + path); + + if (matchEx) { + excluded = true; + break ex; + } + } + if (!excluded) + return true; + } + } + return false; + } + + protected void uploadFile(Session session, File localFile, String remoteFile) { InputStream in = null; OutputStream channelOut; InputStream channelIn; - - Session session = openSession(); try { // exec 'scp -t rfile' remotely @@ -42,14 +147,13 @@ public class ScpTo extends AbstractJschTask { // send "C0644 filesize filename", where filename should not include // '/' - File lFile = localFile.getFile(); - long filesize = lFile.length(); + long filesize = localFile.length(); command = "C0644 " + filesize + " "; - int index = lFile.getPath().lastIndexOf('/'); + int index = localFile.getPath().lastIndexOf('/'); if (index > 0) { - command += lFile.getPath().substring(index + 1); + command += localFile.getPath().substring(index + 1); } else { - command += lFile.getPath(); + command += localFile.getPath(); } command += "\n"; @@ -57,12 +161,15 @@ public class ScpTo extends AbstractJschTask { channelOut.flush(); checkAck(channelIn); - if (log.isDebugEnabled()) + if (log.isTraceEnabled()) log.debug("Start copy of " + localFile + " to " + remoteFile + " on " + getSshTarget() + "..."); + final long oneMB = 1024l;// in KB + final long tenMB = 10 * oneMB;// in KB + // send a content of lfile - in = localFile.getInputStream(); + in = new FileInputStream(localFile); byte[] buf = new byte[1024]; long cycleCount = 0; while (true) { @@ -70,8 +177,11 @@ public class ScpTo extends AbstractJschTask { if (len <= 0) break; channelOut.write(buf, 0, len); // out.flush(); - if ((cycleCount % 1024) == 0)// each 1 MB + if (((cycleCount % oneMB) == 0) && cycleCount != 0)// each 1 MB System.out.print('#'); + if (((cycleCount % (tenMB)) == 0) && cycleCount != 0)// each 10 + // MB + System.out.print(" - " + cycleCount / tenMB + "0 MB\n"); cycleCount++; } // send '\0' @@ -80,15 +190,17 @@ public class ScpTo extends AbstractJschTask { channelOut.flush(); checkAck(channelIn); + if (log.isTraceEnabled()) + log.debug((cycleCount) + " KB sent to server. (" + + (cycleCount / oneMB + " MB)")); + if (log.isDebugEnabled()) - log.debug("Finished copy of " + localFile + " to " + remoteFile - + " on " + getSshTarget() + "..."); + log.debug("Finished copy to " + remoteFile + " on " + + getSshTarget() + " from " + localFile); IOUtils.closeQuietly(channelOut); channel.disconnect(); - session.disconnect(); - } catch (Exception e) { throw new SlcException("Cannot copy " + localFile + " to " + remoteFile, e); @@ -97,12 +209,32 @@ public class ScpTo extends AbstractJschTask { } } - public void setLocalFile(Resource localFile) { - this.localFile = localFile; + public void setLocalResource(Resource localFile) { + this.localResource = localFile; + } + + public void setRemotePath(String remoteFile) { + this.remotePath = remoteFile; + } + + public void setDir(String dir) { + this.dir = dir; + } + + public void setRemoteDir(String remoteDir) { + this.remoteDir = remoteDir; + } + + public void setIncludes(List includes) { + this.includes = includes; + } + + public void setExcludes(List excludes) { + this.excludes = excludes; } - public void setRemoteFile(String remoteFile) { - this.remoteFile = remoteFile; + public void setPathMatcher(PathMatcher pathMatcher) { + this.pathMatcher = pathMatcher; } }