KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > optional > ssh > ScpFromMessage


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs.optional.ssh;
20
21 import java.io.File JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.EOFException JavaDoc;
24 import java.io.InputStream JavaDoc;
25 import java.io.OutputStream JavaDoc;
26 import java.io.FileOutputStream JavaDoc;
27 import java.io.ByteArrayOutputStream JavaDoc;
28 import com.jcraft.jsch.JSchException;
29 import com.jcraft.jsch.Session;
30 import com.jcraft.jsch.Channel;
31
32 /**
33  * A helper object representing an scp download.
34  */

35 public class ScpFromMessage extends AbstractSshMessage {
36
37     private static final byte LINE_FEED = 0x0a;
38     private static final int BUFFER_SIZE = 1024;
39
40     private String JavaDoc remoteFile;
41     private File JavaDoc localFile;
42     private boolean isRecursive = false;
43
44     /**
45      * Constructor for ScpFromMessage
46      * @param session the ssh session to use
47      */

48     public ScpFromMessage(Session session) {
49         super(session);
50     }
51
52     /**
53      * Constructor for ScpFromMessage
54      * @param verbose if true do verbose logging
55      * @param session the ssh session to use
56      * @since Ant 1.7
57      */

58     public ScpFromMessage(boolean verbose, Session session) {
59         super(verbose, session);
60     }
61
62     /**
63      * Constructor for ScpFromMessage.
64      * @param verbose if true log extra information
65      * @param session the Scp session to use
66      * @param aRemoteFile the remote file name
67      * @param aLocalFile the local file
68      * @param recursive if true use recursion (-r option to scp)
69      * @since Ant 1.6.2
70      */

71     public ScpFromMessage(boolean verbose,
72                           Session session,
73                           String JavaDoc aRemoteFile,
74                           File JavaDoc aLocalFile,
75                           boolean recursive) {
76         super(verbose, session);
77         this.remoteFile = aRemoteFile;
78         this.localFile = aLocalFile;
79         this.isRecursive = recursive;
80     }
81
82     /**
83      * Constructor for ScpFromMessage.
84      * @param session the Scp session to use
85      * @param aRemoteFile the remote file name
86      * @param aLocalFile the local file
87      * @param recursive if true use recursion (-r option to scp)
88      */

89     public ScpFromMessage(Session session,
90                            String JavaDoc aRemoteFile,
91                            File JavaDoc aLocalFile,
92                            boolean recursive) {
93         this(false, session, aRemoteFile, aLocalFile, recursive);
94     }
95
96     /**
97      * Carry out the transfer.
98      * @throws IOException on i/o errors
99      * @throws JSchException on errors detected by scp
100      */

101     public void execute() throws IOException JavaDoc, JSchException {
102         String JavaDoc command = "scp -f ";
103         if (isRecursive) {
104             command += "-r ";
105         }
106         command += remoteFile;
107         Channel channel = openExecChannel(command);
108         try {
109             // get I/O streams for remote scp
110
OutputStream JavaDoc out = channel.getOutputStream();
111             InputStream JavaDoc in = channel.getInputStream();
112
113             channel.connect();
114
115             sendAck(out);
116             startRemoteCpProtocol(in, out, localFile);
117         } finally {
118             if (channel != null) {
119                 channel.disconnect();
120             }
121         }
122         log("done\n");
123     }
124
125     private void startRemoteCpProtocol(InputStream JavaDoc in,
126                                        OutputStream JavaDoc out,
127                                        File JavaDoc localFile) throws IOException JavaDoc {
128         File JavaDoc startFile = localFile;
129         while (true) {
130             // C0644 filesize filename - header for a regular file
131
// T time 0 time 0\n - present if perserve time.
132
// D directory - this is the header for a directory.
133
ByteArrayOutputStream JavaDoc stream = new ByteArrayOutputStream JavaDoc();
134             while (true) {
135                 int read = in.read();
136                 if (read < 0) {
137                     return;
138                 }
139                 if ((byte) read == LINE_FEED) {
140                     break;
141                 }
142                 stream.write(read);
143             }
144             String JavaDoc serverResponse = stream.toString("UTF-8");
145             if (serverResponse.charAt(0) == 'C') {
146                 parseAndFetchFile(serverResponse, startFile, out, in);
147             } else if (serverResponse.charAt(0) == 'D') {
148                 startFile = parseAndCreateDirectory(serverResponse,
149                         startFile);
150                 sendAck(out);
151             } else if (serverResponse.charAt(0) == 'E') {
152                 startFile = startFile.getParentFile();
153                 sendAck(out);
154             } else if (serverResponse.charAt(0) == '\01'
155                     || serverResponse.charAt(0) == '\02') {
156                 // this indicates an error.
157
throw new IOException JavaDoc(serverResponse.substring(1));
158             }
159         }
160     }
161
162     private File JavaDoc parseAndCreateDirectory(String JavaDoc serverResponse,
163                                          File JavaDoc localFile) {
164         int start = serverResponse.indexOf(" ");
165         // appears that the next token is not used and it's zero.
166
start = serverResponse.indexOf(" ", start + 1);
167         String JavaDoc directoryName = serverResponse.substring(start + 1);
168         if (localFile.isDirectory()) {
169             File JavaDoc dir = new File JavaDoc(localFile, directoryName);
170             dir.mkdir();
171             log("Creating: " + dir);
172             return dir;
173         }
174         return null;
175     }
176
177     private void parseAndFetchFile(String JavaDoc serverResponse,
178                                    File JavaDoc localFile,
179                                    OutputStream JavaDoc out,
180                                    InputStream JavaDoc in) throws IOException JavaDoc {
181         int start = 0;
182         int end = serverResponse.indexOf(" ", start + 1);
183         start = end + 1;
184         end = serverResponse.indexOf(" ", start + 1);
185         long filesize = Long.parseLong(serverResponse.substring(start, end));
186         String JavaDoc filename = serverResponse.substring(end + 1);
187         log("Receiving: " + filename + " : " + filesize);
188         File JavaDoc transferFile = (localFile.isDirectory())
189                 ? new File JavaDoc(localFile, filename)
190                 : localFile;
191         fetchFile(transferFile, filesize, out, in);
192         waitForAck(in);
193         sendAck(out);
194     }
195
196     private void fetchFile(File JavaDoc localFile,
197                             long filesize,
198                             OutputStream JavaDoc out,
199                             InputStream JavaDoc in) throws IOException JavaDoc {
200         byte[] buf = new byte[BUFFER_SIZE];
201         sendAck(out);
202
203         // read a content of lfile
204
FileOutputStream JavaDoc fos = new FileOutputStream JavaDoc(localFile);
205         int length;
206         long totalLength = 0;
207         long startTime = System.currentTimeMillis();
208
209         // only track progress for files larger than 100kb in verbose mode
210
boolean trackProgress = getVerbose() && filesize > 102400;
211         // since filesize keeps on decreasing we have to store the
212
// initial filesize
213
long initFilesize = filesize;
214         int percentTransmitted = 0;
215
216         try {
217             while (true) {
218                 length = in.read(buf, 0,
219                                  (BUFFER_SIZE < filesize) ? BUFFER_SIZE
220                                                           : (int) filesize);
221                 if (length < 0) {
222                     throw new EOFException JavaDoc("Unexpected end of stream.");
223                 }
224                 fos.write(buf, 0, length);
225                 filesize -= length;
226                 totalLength += length;
227                 if (filesize == 0) {
228                     break;
229                 }
230
231                 if (trackProgress) {
232                     percentTransmitted = trackProgress(initFilesize,
233                                                        totalLength,
234                                                        percentTransmitted);
235                 }
236             }
237         } finally {
238             long endTime = System.currentTimeMillis();
239             logStats(startTime, endTime, totalLength);
240             fos.flush();
241             fos.close();
242         }
243     }
244
245 }
246
Popular Tags