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
.argeo
.api
.cms
.CmsLog
;
16 import org
.argeo
.slc
.SlcException
;
17 import org
.springframework
.core
.io
.ByteArrayResource
;
18 import org
.springframework
.core
.io
.Resource
;
19 import org
.springframework
.util
.AntPathMatcher
;
20 import org
.springframework
.util
.PathMatcher
;
21 import org
.springframework
.util
.StringUtils
;
23 import com
.jcraft
.jsch
.Channel
;
24 import com
.jcraft
.jsch
.ChannelExec
;
25 import com
.jcraft
.jsch
.Session
;
27 public class ScpTo
extends AbstractJschTask
{
28 private final static CmsLog log
= CmsLog
.getLog(ScpTo
.class);
30 private Resource localResource
;
31 private String remotePath
;
34 private String remoteDir
;
35 private List
<String
> includes
= new ArrayList
<String
>();
37 private List
<String
> excludes
= new ArrayList
<String
>();
39 private PathMatcher pathMatcher
;
41 public void run(Session session
) {
42 if (StringUtils
.hasText(dir
)) {
43 if (!StringUtils
.hasText(remoteDir
))
44 throw new SlcException("Remote dir has to be specified.");
46 String dirOs
= dir
.replace('/', File
.separatorChar
);
47 if (dirOs
.charAt(dir
.length() - 1) != File
.separatorChar
) {
48 dirOs
= dirOs
+ File
.separator
;
51 if (pathMatcher
== null)
52 pathMatcher
= new AntPathMatcher();
54 log
.info("Start multiple scp based on " + dirOs
);
55 scanDir(session
, dirOs
, "", includes
, excludes
);
58 if (localResource
!= null) {
59 uploadResource(session
, localResource
);
63 protected void scanDir(Session session
, String dir
, String currentRelPath
,
64 List
<String
> includes
, List
<String
> excludes
) {
65 File
[] files
= new File(dir
).listFiles();
66 for (File file
: files
) {
67 if (!file
.isDirectory()) {
68 String relPath
= currentRelPath
.concat(file
.getName());
69 if (match(relPath
, includes
, excludes
, false)) {
70 uploadFile(session
, file
, remoteDir
+ '/' + relPath
);
73 String relPath
= currentRelPath
.concat(file
.getName()).concat(
75 if (match(relPath
, includes
, excludes
, true)) {
76 String nextDir
= dir
.concat(file
.getName()).concat(
78 scanDir(session
, nextDir
, relPath
, includes
, excludes
);
84 protected Boolean
match(String path
, List
<String
> includes
,
85 List
<String
> excludes
, boolean matchStart
) {
86 for (String patternIn
: includes
) {
87 boolean matchIn
= matchStart ? pathMatcher
.matchStart(patternIn
,
88 path
) : pathMatcher
.match(patternIn
, path
);
90 // Could be included, check excludes
91 boolean excluded
= false;
92 ex
: for (String patternEx
: excludes
) {
93 boolean matchEx
= matchStart ? pathMatcher
.matchStart(
94 patternEx
, path
) : pathMatcher
.match(patternEx
,
109 protected void uploadFile(Session session
, File file
, String remoteFile
) {
111 upload(session
, new FileInputStream(file
), file
.length(), file
112 .getPath(), file
.toString(), remoteFile
);
113 } catch (FileNotFoundException e
) {
114 throw new SlcException("Cannot upload " + file
, e
);
118 protected void uploadResource(Session session
, Resource resource
) {
119 String targetPath
= remotePath
!= null ? remotePath
: remoteDir
+ '/'
120 + resource
.getFilename();
122 File lFile
= resource
.getFile();
123 uploadFile(session
, lFile
, targetPath
);
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();
140 if (path
.startsWith("/"))
141 path
= path
.substring(1);
143 ByteArrayInputStream content
= new ByteArrayInputStream(arr
);
144 upload(session
, content
, arr
.length
, path
, resource
.toString(),
147 } catch (IOException e1
) {
148 throw new SlcException("Can not interpret resource "
149 + localResource
, e1
);
151 IOUtils
.closeQuietly(in
);
152 // no need to close byte arrays streams
157 protected void upload(Session session
, InputStream in
, long size
,
158 String path
, String sourceDesc
, String remoteFile
) {
159 OutputStream channelOut
;
160 InputStream channelIn
;
163 // exec 'scp -t rfile' remotely
164 String command
= "scp -p -t " + remoteFile
;
165 Channel channel
= session
.openChannel("exec");
166 ((ChannelExec
) channel
).setCommand(command
);
168 // get I/O streams for remote scp
169 channelOut
= channel
.getOutputStream();
170 channelIn
= channel
.getInputStream();
175 // send "C0644 filesize filename", where filename should not include
177 long filesize
= size
;
178 command
= "C0644 " + filesize
+ " ";
179 int index
= path
.lastIndexOf('/');
181 command
+= path
.substring(index
+ 1);
187 channelOut
.write(command
.getBytes());
191 if (log
.isTraceEnabled())
192 log
.debug("Start copy of " + sourceDesc
+ " to " + remoteFile
193 + " on " + getSshTarget() + "...");
195 final long oneMB
= 1024l;// in KB
196 final long tenMB
= 10 * oneMB
;// in KB
198 // send a content of lfile
199 byte[] buf
= new byte[1024];
203 int len
= in
.read(buf
, 0, buf
.length
);
206 channelOut
.write(buf
, 0, len
); // out.flush();
207 nbrOfBytes
= nbrOfBytes
+ len
;
208 if (((cycleCount
% oneMB
) == 0) && cycleCount
!= 0)// each 1 MB
209 System
.out
.print('#');
210 if (((cycleCount
% (tenMB
)) == 0) && cycleCount
!= 0)// each 10
212 System
.out
.print(" - " + cycleCount
/ tenMB
+ "0 MB\n");
217 channelOut
.write(buf
, 0, 1);
221 if (log
.isDebugEnabled())
222 log
.debug("Transferred to " + remoteFile
+ " ("
223 + sizeDesc(nbrOfBytes
) + ") on " + getSshTarget()
224 + " from " + sourceDesc
);
226 IOUtils
.closeQuietly(channelOut
);
228 channel
.disconnect();
229 } catch (Exception e
) {
230 throw new SlcException("Cannot copy " + path
+ " to " + remoteFile
,
233 IOUtils
.closeQuietly(in
);
237 protected String
sizeDesc(Long nbrOfBytes
) {
238 if (nbrOfBytes
< 1024)
239 return nbrOfBytes
+ " B";
240 else if (nbrOfBytes
< 1024 * 1024)
241 return (nbrOfBytes
/ 1024) + " KB";
243 return nbrOfBytes
/ (1024 * 1024) + " MB";
246 public void setLocalResource(Resource localFile
) {
247 this.localResource
= localFile
;
250 public void setRemotePath(String remoteFile
) {
251 this.remotePath
= remoteFile
;
254 public void setDir(String dir
) {
258 public void setRemoteDir(String remoteDir
) {
259 this.remoteDir
= remoteDir
;
262 public void setIncludes(List
<String
> includes
) {
263 this.includes
= includes
;
266 public void setExcludes(List
<String
> excludes
) {
267 this.excludes
= excludes
;
270 public void setPathMatcher(PathMatcher pathMatcher
) {
271 this.pathMatcher
= pathMatcher
;