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