]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java
Improve JSCH support
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.simple / src / main / java / org / argeo / slc / jsch / ScpTo.java
index d10125fe77005431ac8b8d2f35e186d0a053fe3c..07f428c4df03de90537fdf8bd5d97881fe665ee0 100644 (file)
@@ -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<String> includes = new ArrayList<String>();
+
+       private List<String> excludes = new ArrayList<String>();
+
+       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<String> includes, List<String> 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<String> includes,
+                       List<String> 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<String> includes) {
+               this.includes = includes;
+       }
+
+       public void setExcludes(List<String> excludes) {
+               this.excludes = excludes;
        }
 
-       public void setRemoteFile(String remoteFile) {
-               this.remoteFile = remoteFile;
+       public void setPathMatcher(PathMatcher pathMatcher) {
+               this.pathMatcher = pathMatcher;
        }
 
 }