1 package org
.argeo
.slc
.jsch
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.ByteArrayOutputStream
;
6 import java
.io
.FileInputStream
;
7 import java
.io
.FileNotFoundException
;
8 import java
.io
.IOException
;
9 import java
.io
.InputStream
;
10 import java
.io
.OutputStream
;
11 import java
.util
.ArrayList
;
12 import java
.util
.List
;
14 import org
.apache
.commons
.io
.IOUtils
;
15 import org
.apache
.commons
.logging
.Log
;
16 import org
.apache
.commons
.logging
.LogFactory
;
17 import org
.argeo
.slc
.SlcException
;
18 import org
.springframework
.core
.io
.ByteArrayResource
;
19 import org
.springframework
.core
.io
.Resource
;
20 import org
.springframework
.util
.AntPathMatcher
;
21 import org
.springframework
.util
.PathMatcher
;
22 import org
.springframework
.util
.StringUtils
;
24 import com
.jcraft
.jsch
.Channel
;
25 import com
.jcraft
.jsch
.ChannelExec
;
26 import com
.jcraft
.jsch
.Session
;
28 public class ScpTo
extends AbstractJschTask
{
29 private final static Log log
= LogFactory
.getLog(ScpTo
.class);
31 private Resource localResource
;
32 private String remotePath
;
35 private String remoteDir
;
36 private List
<String
> includes
= new ArrayList
<String
>();
38 private List
<String
> excludes
= new ArrayList
<String
>();
40 private PathMatcher pathMatcher
;
42 public void run(Session session
) {
43 if (StringUtils
.hasText(dir
)) {
44 if (!StringUtils
.hasText(remoteDir
))
45 throw new SlcException("Remote dir has to be specified.");
47 String dirOs
= dir
.replace('/', File
.separatorChar
);
48 if (dirOs
.charAt(dir
.length() - 1) != File
.separatorChar
) {
49 dirOs
= dirOs
+ File
.separator
;
52 if (pathMatcher
== null)
53 pathMatcher
= new AntPathMatcher();
55 log
.info("Start multiple scp based on " + dirOs
);
56 scanDir(session
, dirOs
, "", includes
, excludes
);
59 if (localResource
!= null) {
60 uploadResource(session
, localResource
, remoteDir
);
64 protected void scanDir(Session session
, String dir
, String currentRelPath
,
65 List
<String
> includes
, List
<String
> excludes
) {
66 File
[] files
= new File(dir
).listFiles();
67 for (File file
: files
) {
68 if (!file
.isDirectory()) {
69 String relPath
= currentRelPath
.concat(file
.getName());
70 if (match(relPath
, includes
, excludes
, false)) {
71 uploadFile(session
, file
, remoteDir
+ '/' + relPath
);
74 String relPath
= currentRelPath
.concat(file
.getName()).concat(
76 if (match(relPath
, includes
, excludes
, true)) {
77 String nextDir
= dir
.concat(file
.getName()).concat(
79 scanDir(session
, nextDir
, relPath
, includes
, excludes
);
85 protected Boolean
match(String path
, List
<String
> includes
,
86 List
<String
> excludes
, boolean matchStart
) {
87 for (String patternIn
: includes
) {
88 boolean matchIn
= matchStart ? pathMatcher
.matchStart(patternIn
,
89 path
) : pathMatcher
.match(patternIn
, path
);
91 // Could be included, check excludes
92 boolean excluded
= false;
93 ex
: for (String patternEx
: excludes
) {
94 boolean matchEx
= matchStart ? pathMatcher
.matchStart(
95 patternEx
, path
) : pathMatcher
.match(patternEx
,
110 protected void uploadFile(Session session
, File file
, String remoteFile
) {
112 uploadFile(session
, new FileInputStream(file
), file
.length(), file
113 .getPath(), file
.toString(), remoteFile
);
114 } catch (FileNotFoundException e
) {
115 throw new SlcException("Cannot upload " + file
, e
);
119 protected void uploadResource(Session session
, Resource resource
,
122 File lFile
= resource
.getFile();
123 uploadFile(session
, lFile
, remotePath
);
124 } catch (IOException e
) {
125 // no underlying file found
126 // load the resource in memory before transferring it
127 InputStream in
= null;
131 if (resource
instanceof ByteArrayResource
) {
132 arr
= ((ByteArrayResource
) resource
).getByteArray();
135 in
= resource
.getInputStream();
136 ByteArrayOutputStream out
= new ByteArrayOutputStream();
137 IOUtils
.copy(in
, out
);
138 arr
= out
.toByteArray();
139 path
= resource
.getURL().getPath();
141 ByteArrayInputStream content
= new ByteArrayInputStream(arr
);
142 uploadFile(session
, content
, arr
.length
, path
, resource
143 .toString(), remotePath
);
145 } catch (IOException e1
) {
146 throw new SlcException("Can not interpret resource "
147 + localResource
, e1
);
149 IOUtils
.closeQuietly(in
);
150 // no need to close byte arrays streams
155 protected void uploadFile(Session session
, InputStream in
, long size
,
156 String path
, String sourceDesc
, String remoteFile
) {
157 OutputStream channelOut
;
158 InputStream channelIn
;
161 // exec 'scp -t rfile' remotely
162 String command
= "scp -p -t " + remoteFile
;
163 Channel channel
= session
.openChannel("exec");
164 ((ChannelExec
) channel
).setCommand(command
);
166 // get I/O streams for remote scp
167 channelOut
= channel
.getOutputStream();
168 channelIn
= channel
.getInputStream();
173 // send "C0644 filesize filename", where filename should not include
175 long filesize
= size
;
176 command
= "C0644 " + filesize
+ " ";
177 int index
= path
.lastIndexOf('/');
179 command
+= path
.substring(index
+ 1);
185 channelOut
.write(command
.getBytes());
189 if (log
.isTraceEnabled())
190 log
.debug("Start copy of " + sourceDesc
+ " to " + remoteFile
191 + " on " + getSshTarget() + "...");
193 final long oneMB
= 1024l;// in KB
194 final long tenMB
= 10 * oneMB
;// in KB
196 // send a content of lfile
197 byte[] buf
= new byte[1024];
201 int len
= in
.read(buf
, 0, buf
.length
);
204 channelOut
.write(buf
, 0, len
); // out.flush();
205 nbrOfBytes
= nbrOfBytes
+ len
;
206 if (((cycleCount
% oneMB
) == 0) && cycleCount
!= 0)// each 1 MB
207 System
.out
.print('#');
208 if (((cycleCount
% (tenMB
)) == 0) && cycleCount
!= 0)// each 10
210 System
.out
.print(" - " + cycleCount
/ tenMB
+ "0 MB\n");
215 channelOut
.write(buf
, 0, 1);
219 if (log
.isDebugEnabled())
220 log
.debug("Transferred to " + remoteFile
+ " ("
221 + sizeDesc(nbrOfBytes
) + ") on " + getSshTarget()
222 + " from " + sourceDesc
);
224 IOUtils
.closeQuietly(channelOut
);
226 channel
.disconnect();
227 } catch (Exception e
) {
228 throw new SlcException("Cannot copy " + path
+ " to " + remoteFile
,
231 IOUtils
.closeQuietly(in
);
235 protected String
sizeDesc(Long nbrOfBytes
) {
236 if (nbrOfBytes
< 1024)
237 return nbrOfBytes
+ " B";
238 else if (nbrOfBytes
< 1024 * 1024)
239 return (nbrOfBytes
/ 1024) + " KB";
241 return nbrOfBytes
/ (1024 * 1024) + " MB";
244 public void setLocalResource(Resource localFile
) {
245 this.localResource
= localFile
;
248 public void setRemotePath(String remoteFile
) {
249 this.remotePath
= remoteFile
;
252 public void setDir(String dir
) {
256 public void setRemoteDir(String remoteDir
) {
257 this.remoteDir
= remoteDir
;
260 public void setIncludes(List
<String
> includes
) {
261 this.includes
= includes
;
264 public void setExcludes(List
<String
> excludes
) {
265 this.excludes
= excludes
;
268 public void setPathMatcher(PathMatcher pathMatcher
) {
269 this.pathMatcher
= pathMatcher
;