]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/jsch/ScpTo.java
Add SCP From
[gpl/argeo-slc.git] / runtime / org.argeo.slc.support.simple / src / main / java / org / argeo / slc / jsch / ScpTo.java
1 package org.argeo.slc.jsch;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.util.ArrayList;
9 import java.util.List;
10
11 import org.apache.commons.io.IOUtils;
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.argeo.slc.SlcException;
15 import org.springframework.core.io.Resource;
16 import org.springframework.util.AntPathMatcher;
17 import org.springframework.util.PathMatcher;
18 import org.springframework.util.StringUtils;
19
20 import com.jcraft.jsch.Channel;
21 import com.jcraft.jsch.ChannelExec;
22 import com.jcraft.jsch.Session;
23
24 public class ScpTo extends AbstractJschTask {
25 private final static Log log = LogFactory.getLog(ScpTo.class);
26
27 private Resource localResource;
28 private String remotePath;
29
30 private String dir;
31 private String remoteDir;
32 private List<String> includes = new ArrayList<String>();
33
34 private List<String> excludes = new ArrayList<String>();
35
36 private PathMatcher pathMatcher;
37
38 public void run(Session session) {
39 if (StringUtils.hasText(dir)) {
40 if (!StringUtils.hasText(remoteDir))
41 throw new SlcException("Remote dir has to be specified.");
42
43 String dirOs = dir.replace('/', File.separatorChar);
44 if (dirOs.charAt(dir.length() - 1) != File.separatorChar) {
45 dirOs = dirOs + File.separator;
46 }
47
48 if (pathMatcher == null)
49 pathMatcher = new AntPathMatcher();
50
51 log.info("Start multiple scp based on "+dirOs);
52 scanDir(session, dirOs, "", includes, excludes);
53 }
54
55 if (localResource != null) {
56 File lFile;
57 try {
58 lFile = localResource.getFile();
59 } catch (IOException e) {
60 throw new SlcException("Cannot interpret resource "
61 + localResource + " as file.", e);
62 }
63 uploadFile(session, lFile, remotePath);
64 }
65 }
66
67 protected void scanDir(Session session, String dir, String currentRelPath,
68 List<String> includes, List<String> excludes) {
69 File[] files = new File(dir).listFiles();
70 for (File file : files) {
71 if (!file.isDirectory()) {
72 String relPath = currentRelPath.concat(file.getName());
73 if (match(relPath, includes, excludes, false)) {
74 uploadFile(session, file, remoteDir + '/' + relPath);
75 }
76 } else {
77 String relPath = currentRelPath.concat(file.getName()).concat(
78 "/");
79 if (match(relPath, includes, excludes, true)) {
80 String nextDir = dir.concat(file.getName()).concat(
81 File.separator);
82 scanDir(session, nextDir, relPath, includes, excludes);
83 }
84 }
85 }
86 }
87
88 protected Boolean match(String path, List<String> includes,
89 List<String> excludes, boolean matchStart) {
90 for (String patternIn : includes) {
91 boolean matchIn = matchStart ? pathMatcher.matchStart(patternIn,
92 path) : pathMatcher.match(patternIn, path);
93 if (matchIn) {
94 // Could be included, check excludes
95 boolean excluded = false;
96 ex: for (String patternEx : excludes) {
97 boolean matchEx = matchStart ? pathMatcher.matchStart(
98 patternEx, path) : pathMatcher.match(patternEx,
99 path);
100
101 if (matchEx) {
102 excluded = true;
103 break ex;
104 }
105 }
106 if (!excluded)
107 return true;
108 }
109 }
110 return false;
111 }
112
113 protected void uploadFile(Session session, File localFile, String remoteFile) {
114 InputStream in = null;
115 OutputStream channelOut;
116 InputStream channelIn;
117 try {
118
119 // exec 'scp -t rfile' remotely
120 String command = "scp -p -t " + remoteFile;
121 Channel channel = session.openChannel("exec");
122 ((ChannelExec) channel).setCommand(command);
123
124 // get I/O streams for remote scp
125 channelOut = channel.getOutputStream();
126 channelIn = channel.getInputStream();
127
128 channel.connect();
129 checkAck(channelIn);
130
131 // send "C0644 filesize filename", where filename should not include
132 // '/'
133 long filesize = localFile.length();
134 command = "C0644 " + filesize + " ";
135 int index = localFile.getPath().lastIndexOf('/');
136 if (index > 0) {
137 command += localFile.getPath().substring(index + 1);
138 } else {
139 command += localFile.getPath();
140 }
141 command += "\n";
142
143 channelOut.write(command.getBytes());
144 channelOut.flush();
145 checkAck(channelIn);
146
147 if (log.isDebugEnabled())
148 log.debug("Start copy of " + localFile + " to " + remoteFile
149 + " on " + getSshTarget() + "...");
150
151 final long oneMB = 1024l;// in KB
152 final long tenMB = 10 * oneMB;// in KB
153
154 // send a content of lfile
155 in = new FileInputStream(localFile);
156 byte[] buf = new byte[1024];
157 long cycleCount = 0;
158 while (true) {
159 int len = in.read(buf, 0, buf.length);
160 if (len <= 0)
161 break;
162 channelOut.write(buf, 0, len); // out.flush();
163 if ((cycleCount % oneMB) == 0)// each 1 MB
164 System.out.print('#');
165 if ((cycleCount % (tenMB)) == 0)// each 10 MB
166 System.out.print(" - " + cycleCount / tenMB + "0 MB\n");
167 cycleCount++;
168 }
169 // send '\0'
170 buf[0] = 0;
171 channelOut.write(buf, 0, 1);
172 channelOut.flush();
173 checkAck(channelIn);
174
175 log.info("\n" + (cycleCount) + " KB sent to server. ("
176 + (cycleCount / oneMB + " MB)"));
177
178 if (log.isDebugEnabled())
179 log.debug("Finished copy of " + localFile + " to " + remoteFile
180 + " on " + getSshTarget() + "...");
181
182 IOUtils.closeQuietly(channelOut);
183
184 channel.disconnect();
185 } catch (Exception e) {
186 throw new SlcException("Cannot copy " + localFile + " to "
187 + remoteFile, e);
188 } finally {
189 IOUtils.closeQuietly(in);
190 }
191 }
192
193 public void setLocalResource(Resource localFile) {
194 this.localResource = localFile;
195 }
196
197 public void setRemotePath(String remoteFile) {
198 this.remotePath = remoteFile;
199 }
200
201 public void setDir(String dir) {
202 this.dir = dir;
203 }
204
205 public void setRemoteDir(String remoteDir) {
206 this.remoteDir = remoteDir;
207 }
208
209 public void setIncludes(List<String> includes) {
210 this.includes = includes;
211 }
212
213 public void setExcludes(List<String> excludes) {
214 this.excludes = excludes;
215 }
216
217 public void setPathMatcher(PathMatcher pathMatcher) {
218 this.pathMatcher = pathMatcher;
219 }
220
221 }