KickJava   Java API By Example, From Geeks To Geeks.

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


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 com.jcraft.jsch.JSchException;
22 import com.jcraft.jsch.Session;
23
24 import java.io.IOException JavaDoc;
25 import java.io.File JavaDoc;
26
27 import java.util.List JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.ArrayList JavaDoc;
31
32 import org.apache.tools.ant.BuildException;
33 import org.apache.tools.ant.DirectoryScanner;
34 import org.apache.tools.ant.Project;
35 import org.apache.tools.ant.types.FileSet;
36
37 /**
38  * Ant task for sending files to remote machine over ssh/scp.
39  *
40  * @since Ant 1.6
41  */

42 public class Scp extends SSHBase {
43
44     private static final String JavaDoc[] FROM_ATTRS = {
45         "file", "localfile", "remotefile" };
46
47     private static final String JavaDoc[] TO_ATTRS = {
48         "todir", "localtodir", "remotetodir", "localtofile", "remotetofile" };
49
50     private String JavaDoc fromUri;
51     private String JavaDoc toUri;
52     private List JavaDoc fileSets = null;
53     private boolean isFromRemote, isToRemote;
54     private boolean isSftp = false;
55
56     /**
57      * Sets the file to be transferred. This can either be a remote
58      * file or a local file. Remote files take the form:<br>
59      * <i>user:password@host:/directory/path/file.example</i><br>
60      * Files to transfer can also include a wildcard to include all
61      * files in a remote directory. For example:<br>
62      * <i>user:password@host:/directory/path/*</i><br>
63      * @param aFromUri a string representing the file to transfer.
64      */

65     public void setFile(String JavaDoc aFromUri) {
66         setFromUri(aFromUri);
67         this.isFromRemote = isRemoteUri(this.fromUri);
68     }
69
70     /**
71      * Sets the location where files will be transferred to.
72      * This can either be a remote directory or a local directory.
73      * Remote directories take the form of:<br>
74      * <i>user:password@host:/directory/path/</i><br>
75      * This parameter is required.
76
77      * @param aToUri a string representing the target of the copy.
78      */

79     public void setTodir(String JavaDoc aToUri) {
80         setToUri(aToUri);
81         this.isToRemote = isRemoteUri(this.toUri);
82     }
83
84     /**
85      * Similiar to {@link #setFile setFile} but explicitly states that
86      * the file is a local file. This is the only way to specify a
87      * local file with a @ character.
88      * @param aFromUri a string representing the source of the copy.
89      * @since Ant 1.6.2
90      */

91     public void setLocalFile(String JavaDoc aFromUri) {
92         setFromUri(aFromUri);
93         this.isFromRemote = false;
94     }
95
96     /**
97      * Similiar to {@link #setFile setFile} but explicitly states that
98      * the file is a remote file.
99      * @param aFromUri a string representing the source of the copy.
100      * @since Ant 1.6.2
101      */

102     public void setRemoteFile(String JavaDoc aFromUri) {
103         setFromUri(aFromUri);
104         this.isFromRemote = true;
105      }
106
107     /**
108      * Similiar to {@link #setTodir setTodir} but explicitly states
109      * that the directory is a local. This is the only way to specify
110      * a local directory with a @ character.
111      * @param aToUri a string representing the target of the copy.
112      * @since Ant 1.6.2
113      */

114     public void setLocalTodir(String JavaDoc aToUri) {
115         setToUri(aToUri);
116         this.isToRemote = false;
117     }
118
119     /**
120      * Similiar to {@link #setTodir setTodir} but explicitly states
121      * that the directory is a remote.
122      * @param aToUri a string representing the target of the copy.
123      * @since Ant 1.6.2
124      */

125     public void setRemoteTodir(String JavaDoc aToUri) {
126         setToUri(aToUri);
127         this.isToRemote = true;
128     }
129
130     /**
131      * Changes the file name to the given name while receiving it,
132      * only useful if receiving a single file.
133      * @param aToUri a string representing the target of the copy.
134      * @since Ant 1.6.2
135      */

136     public void setLocalTofile(String JavaDoc aToUri) {
137         setToUri(aToUri);
138         this.isToRemote = false;
139     }
140
141     /**
142      * Changes the file name to the given name while sending it,
143      * only useful if sending a single file.
144      * @param aToUri a string representing the target of the copy.
145      * @since Ant 1.6.2
146      */

147     public void setRemoteTofile(String JavaDoc aToUri) {
148         setToUri(aToUri);
149         this.isToRemote = true;
150     }
151
152     /**
153      * Setting this to true to use sftp protocol.
154      *
155      * @param yesOrNo if true sftp protocol will be used.
156      */

157     public void setSftp(boolean yesOrNo) {
158         isSftp = yesOrNo;
159     }
160
161     /**
162      * Adds a FileSet tranfer to remote host. NOTE: Either
163      * addFileSet() or setFile() are required. But, not both.
164      *
165      * @param set FileSet to send to remote host.
166      */

167     public void addFileset(FileSet set) {
168         if (fileSets == null) {
169             fileSets = new LinkedList JavaDoc();
170         }
171         fileSets.add(set);
172     }
173
174     /**
175      * Initialize this task.
176      * @throws BuildException on error
177      */

178     public void init() throws BuildException {
179         super.init();
180         this.toUri = null;
181         this.fromUri = null;
182         this.fileSets = null;
183     }
184
185     /**
186      * Execute this task.
187      * @throws BuildException on error
188      */

189     public void execute() throws BuildException {
190         if (toUri == null) {
191             throw exactlyOne(TO_ATTRS);
192         }
193         if (fromUri == null && fileSets == null) {
194             throw exactlyOne(FROM_ATTRS, "one or more nested filesets");
195         }
196         try {
197             if (isFromRemote && !isToRemote) {
198                 download(fromUri, toUri);
199             } else if (!isFromRemote && isToRemote) {
200                 if (fileSets != null) {
201                     upload(fileSets, toUri);
202                 } else {
203                     upload(fromUri, toUri);
204                 }
205             } else if (isFromRemote && isToRemote) {
206                 throw new BuildException(
207                     "Copying from a remote server to a remote server is not supported.");
208             } else {
209                 throw new BuildException("'todir' and 'file' attributes "
210                     + "must have syntax like the following: "
211                     + "user:password@host:/path");
212             }
213         } catch (Exception JavaDoc e) {
214             if (getFailonerror()) {
215                 throw new BuildException(e);
216             } else {
217                 log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
218             }
219         }
220     }
221
222     private void download(String JavaDoc fromSshUri, String JavaDoc toPath)
223         throws JSchException, IOException JavaDoc {
224         String JavaDoc file = parseUri(fromSshUri);
225
226         Session session = null;
227         try {
228             session = openSession();
229             ScpFromMessage message = null;
230             if (!isSftp) {
231                 message =
232                     new ScpFromMessage(getVerbose(), session, file,
233                                        getProject().resolveFile(toPath),
234                                        fromSshUri.endsWith("*"));
235             } else {
236                 message =
237                     new ScpFromMessageBySftp(getVerbose(), session, file,
238                                              getProject().resolveFile(toPath),
239                                              fromSshUri.endsWith("*"));
240             }
241             log("Receiving file: " + file);
242             message.setLogListener(this);
243             message.execute();
244         } finally {
245             if (session != null) {
246                 session.disconnect();
247             }
248         }
249     }
250
251     private void upload(List JavaDoc fileSet, String JavaDoc toSshUri)
252         throws IOException JavaDoc, JSchException {
253         String JavaDoc file = parseUri(toSshUri);
254
255         Session session = null;
256         try {
257             List JavaDoc list = new ArrayList JavaDoc(fileSet.size());
258             for (Iterator JavaDoc i = fileSet.iterator(); i.hasNext();) {
259                 FileSet set = (FileSet) i.next();
260                 Directory d = createDirectory(set);
261                 if (d != null) {
262                     list.add(d);
263                 }
264             }
265             if (!list.isEmpty()) {
266                 session = openSession();
267                 ScpToMessage message = null;
268                 if (!isSftp) {
269                     message = new ScpToMessage(getVerbose(), session,
270                                                list, file);
271                 } else {
272                     message = new ScpToMessageBySftp(getVerbose(), session,
273                                                      list, file);
274                 }
275                 message.setLogListener(this);
276                 message.execute();
277             }
278         } finally {
279             if (session != null) {
280                 session.disconnect();
281             }
282         }
283     }
284
285     private void upload(String JavaDoc fromPath, String JavaDoc toSshUri)
286         throws IOException JavaDoc, JSchException {
287         String JavaDoc file = parseUri(toSshUri);
288
289         Session session = null;
290         try {
291             session = openSession();
292             ScpToMessage message = null;
293             if (!isSftp) {
294                 message =
295                     new ScpToMessage(getVerbose(), session,
296                                      getProject().resolveFile(fromPath), file);
297             } else {
298                 message =
299                     new ScpToMessageBySftp(getVerbose(), session,
300                                            getProject().resolveFile(fromPath),
301                                            file);
302             }
303             message.setLogListener(this);
304             message.execute();
305         } finally {
306             if (session != null) {
307                 session.disconnect();
308             }
309         }
310     }
311
312     private String JavaDoc parseUri(String JavaDoc uri) {
313         int indexOfAt = uri.lastIndexOf('@');
314         int indexOfColon = uri.indexOf(':');
315         if (indexOfColon > -1 && indexOfColon < indexOfAt) {
316             // user:password@host:/path notation
317
setUsername(uri.substring(0, indexOfColon));
318             setPassword(uri.substring(indexOfColon + 1, indexOfAt));
319         } else {
320             // no password, will require passphrase
321
setUsername(uri.substring(0, indexOfAt));
322         }
323
324         if (getUserInfo().getPassword() == null
325             && getUserInfo().getPassphrase() == null) {
326             throw new BuildException("neither password nor passphrase for user "
327                                      + getUserInfo().getName() + " has been "
328                                      + "given. Can't authenticate.");
329         }
330
331         int indexOfPath = uri.indexOf(':', indexOfAt + 1);
332         if (indexOfPath == -1) {
333             throw new BuildException("no remote path in " + uri);
334         }
335
336         setHost(uri.substring(indexOfAt + 1, indexOfPath));
337         String JavaDoc remotePath = uri.substring(indexOfPath + 1);
338         if (remotePath.equals("")) {
339             remotePath = ".";
340         }
341         return remotePath;
342     }
343
344     private boolean isRemoteUri(String JavaDoc uri) {
345         boolean isRemote = true;
346         int indexOfAt = uri.indexOf('@');
347         if (indexOfAt < 0) {
348             isRemote = false;
349         }
350         return isRemote;
351     }
352
353     private Directory createDirectory(FileSet set) {
354         DirectoryScanner scanner = set.getDirectoryScanner(getProject());
355         Directory root = new Directory(scanner.getBasedir());
356         String JavaDoc[] files = scanner.getIncludedFiles();
357         if (files.length != 0) {
358             for (int j = 0; j < files.length; j++) {
359                 String JavaDoc[] path = Directory.getPath(files[j]);
360                 Directory current = root;
361                 File JavaDoc currentParent = scanner.getBasedir();
362                 for (int i = 0; i < path.length; i++) {
363                     File JavaDoc file = new File JavaDoc(currentParent, path[i]);
364                     if (file.isDirectory()) {
365                         current.addDirectory(new Directory(file));
366                         current = current.getChild(file);
367                         currentParent = current.getDirectory();
368                     } else if (file.isFile()) {
369                         current.addFile(file);
370                     }
371                 }
372             }
373         } else {
374             // skip
375
root = null;
376         }
377         return root;
378     }
379
380     private void setFromUri(String JavaDoc fromUri) {
381         if (this.fromUri != null) {
382             throw exactlyOne(FROM_ATTRS);
383         }
384         this.fromUri = fromUri;
385     }
386
387     private void setToUri(String JavaDoc toUri) {
388         if (this.toUri != null) {
389             throw exactlyOne(TO_ATTRS);
390         }
391         this.toUri = toUri;
392     }
393
394     private BuildException exactlyOne(String JavaDoc[] attrs) {
395         return exactlyOne(attrs, null);
396     }
397
398     private BuildException exactlyOne(String JavaDoc[] attrs, String JavaDoc alt) {
399         StringBuffer JavaDoc buf = new StringBuffer JavaDoc("Exactly one of ").append(
400                 '[').append(attrs[0]);
401         for (int i = 1; i < attrs.length; i++) {
402             buf.append('|').append(attrs[i]);
403         }
404         buf.append(']');
405         if (alt != null) {
406             buf.append(" or ").append(alt);
407         }
408         return new BuildException(buf.append(" is required.").toString());
409     }
410 }
411
Popular Tags