source: other-projects/trunk/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/optional/ssh/ScpFromMessage.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 7.4 KB
Line 
1/*
2 * Copyright 2003-2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs.optional.ssh;
19
20import java.util.StringTokenizer;
21import java.io.File;
22import java.io.IOException;
23import java.io.EOFException;
24import java.io.InputStream;
25import java.io.OutputStream;
26import java.io.FileOutputStream;
27import java.io.ByteArrayOutputStream;
28import com.jcraft.jsch.JSchException;
29import com.jcraft.jsch.Session;
30import com.jcraft.jsch.Channel;
31
32public class ScpFromMessage extends AbstractSshMessage {
33
34 private final byte LINE_FEED = 0x0a;
35 private final int BUFFER_SIZE = 1024;
36
37 private String remoteFile;
38 private File localFile;
39 private boolean isRecursive = false;
40
41 /**
42 * @since Ant 1.6.2
43 */
44 public ScpFromMessage(boolean verbose,
45 Session session,
46 String aRemoteFile,
47 File aLocalFile,
48 boolean recursive) {
49 super(verbose, session);
50 this.remoteFile = aRemoteFile;
51 this.localFile = aLocalFile;
52 this.isRecursive = recursive;
53 }
54
55 public ScpFromMessage(Session session,
56 String aRemoteFile,
57 File aLocalFile,
58 boolean recursive) {
59 this(false, session, aRemoteFile, aLocalFile, recursive);
60 }
61
62 public void execute() throws IOException, JSchException {
63 String command = "scp -f ";
64 if (isRecursive) {
65 command += "-r ";
66 }
67 command += remoteFile;
68 Channel channel = openExecChannel(command);
69 try {
70 // get I/O streams for remote scp
71 OutputStream out = channel.getOutputStream();
72 InputStream in = channel.getInputStream();
73
74 channel.connect();
75
76 sendAck(out);
77 startRemoteCpProtocol(in, out, localFile);
78 } finally {
79 if (channel != null) {
80 channel.disconnect();
81 }
82 }
83 log("done\n");
84 }
85
86 private void startRemoteCpProtocol(InputStream in,
87 OutputStream out,
88 File localFile) throws IOException {
89 File startFile = localFile;
90 while (true) {
91 // C0644 filesize filename - header for a regular file
92 // T time 0 time 0\n - present if perserve time.
93 // D directory - this is the header for a directory.
94 ByteArrayOutputStream stream = new ByteArrayOutputStream();
95 while (true) {
96 int read = in.read();
97 if (read < 0) {
98 return;
99 }
100 if ((byte) read == LINE_FEED) {
101 break;
102 }
103 stream.write(read);
104 }
105 String serverResponse = stream.toString("UTF-8");
106 if (serverResponse.charAt(0) == 'C') {
107 parseAndFetchFile(serverResponse, startFile, out, in);
108 } else if (serverResponse.charAt(0) == 'D') {
109 startFile = parseAndCreateDirectory(serverResponse,
110 startFile);
111 sendAck(out);
112 } else if (serverResponse.charAt(0) == 'E') {
113 startFile = startFile.getParentFile();
114 sendAck(out);
115 } else if (serverResponse.charAt(0) == '\01'
116 || serverResponse.charAt(0) == '\02') {
117 // this indicates an error.
118 throw new IOException(serverResponse.substring(1));
119 }
120 }
121 }
122
123 private File parseAndCreateDirectory(String serverResponse,
124 File localFile) {
125 int start = serverResponse.indexOf(" ");
126 // appears that the next token is not used and it's zero.
127 start = serverResponse.indexOf(" ", start + 1);
128 String directoryName = serverResponse.substring(start + 1);
129 if (localFile.isDirectory()) {
130 File dir = new File(localFile, directoryName);
131 dir.mkdir();
132 log("Creating: " + dir);
133 return dir;
134 }
135 return null;
136 }
137
138 private void parseAndFetchFile(String serverResponse,
139 File localFile,
140 OutputStream out,
141 InputStream in) throws IOException {
142 int start = 0;
143 int end = serverResponse.indexOf(" ", start + 1);
144 String command = serverResponse.substring(start, end);
145 start = end + 1;
146 end = serverResponse.indexOf(" ", start + 1);
147 int filesize = Integer.parseInt(serverResponse.substring(start, end));
148 String filename = serverResponse.substring(end + 1);
149 log("Receiving: " + filename + " : " + filesize);
150 File transferFile = (localFile.isDirectory())
151 ? new File(localFile, filename)
152 : localFile;
153 fetchFile(transferFile, filesize, out, in);
154 waitForAck(in);
155 sendAck(out);
156 }
157
158 private void fetchFile(File localFile,
159 int filesize,
160 OutputStream out,
161 InputStream in) throws IOException {
162 byte[] buf = new byte[BUFFER_SIZE];
163 sendAck(out);
164
165 // read a content of lfile
166 FileOutputStream fos = new FileOutputStream(localFile);
167 int length;
168 int totalLength = 0;
169 long startTime = System.currentTimeMillis();
170
171 // only track progress for files larger than 100kb in verbose mode
172 boolean trackProgress = getVerbose() && filesize > 102400;
173 // since filesize keeps on decreasing we have to store the
174 // initial filesize
175 int initFilesize = filesize;
176 int percentTransmitted = 0;
177
178 try {
179 while (true) {
180 length = in.read(buf, 0,
181 (buf.length < filesize) ? buf.length : filesize);
182 if (length < 0) {
183 throw new EOFException("Unexpected end of stream.");
184 }
185 fos.write(buf, 0, length);
186 filesize -= length;
187 totalLength += length;
188 if (filesize == 0) {
189 break;
190 }
191
192 if (trackProgress) {
193 percentTransmitted = trackProgress(initFilesize,
194 totalLength,
195 percentTransmitted);
196 }
197 }
198 } finally {
199 long endTime = System.currentTimeMillis();
200 logStats(startTime, endTime, totalLength);
201 fos.flush();
202 fos.close();
203 }
204 }
205
206}
Note: See TracBrowser for help on using the repository browser.