KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > jayasoft > ivy > repository > sftp > SFTPRepository


1 /*
2  * This file is subject to the licence found in LICENCE.TXT in the root directory of the project.
3  * Copyright Jayasoft 2005 - All rights reserved
4  *
5  * #SNAPSHOT#
6  */

7 package fr.jayasoft.ivy.repository.sftp;
8
9 import java.io.File JavaDoc;
10 import java.io.IOException JavaDoc;
11 import java.io.InputStream JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Collection JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import com.jcraft.jsch.ChannelSftp;
18 import com.jcraft.jsch.JSchException;
19 import com.jcraft.jsch.Session;
20 import com.jcraft.jsch.SftpATTRS;
21 import com.jcraft.jsch.SftpException;
22 import com.jcraft.jsch.SftpProgressMonitor;
23 import com.jcraft.jsch.ChannelSftp.LsEntry;
24
25 import fr.jayasoft.ivy.repository.BasicResource;
26 import fr.jayasoft.ivy.repository.Resource;
27 import fr.jayasoft.ivy.repository.TransferEvent;
28 import fr.jayasoft.ivy.repository.ssh.AbstractSshBasedRepository;
29 import fr.jayasoft.ivy.repository.ssh.SshCache;
30 import fr.jayasoft.ivy.util.Message;
31
32 /**
33  * SFTP Repository, allow to use a repository accessed by sftp protocol.
34  *
35  * It supports all operations: get, put and list.
36  *
37  * It relies on jsch for sftp handling, and thus is compatible with sftp version 0, 1, 2 and 3
38  *
39  * @author Xavier Hanin
40  *
41  */

42 public class SFTPRepository extends AbstractSshBasedRepository {
43     private final class MyProgressMonitor implements SftpProgressMonitor {
44         private long _totalLength;
45
46         public void init(int op, String JavaDoc src, String JavaDoc dest, long max) {
47             _totalLength = max;
48             fireTransferStarted(max);
49         }
50
51         public void end() {
52             fireTransferCompleted(_totalLength);
53         }
54
55         public boolean count(long count) {
56             fireTransferProgress(count);
57             return true;
58         }
59     }
60
61     
62     public SFTPRepository() {
63     }
64
65     
66     public Resource getResource(String JavaDoc source) {
67         return new SFTPResource(this, source);
68     }
69
70
71     /**
72      * This method is similar to getResource, except that the returned resource is fully initialised
73      * (resolved in the sftp repository), and that the given string is a full remote path
74      * @param path the full remote path in the repository of the resource
75      * @return a fully initialised resource, able to answer to all its methods without needing
76      * any further connection
77      */

78     public Resource resolveResource(String JavaDoc path) {
79         try {
80             ChannelSftp c = getSftpChannel(path);
81             Collection JavaDoc r = c.ls(path);
82             if (r != null) {
83                 for (Iterator JavaDoc iter = r.iterator(); iter.hasNext();) {
84                     Object JavaDoc obj=iter.next();
85                     if(obj instanceof LsEntry){
86                         LsEntry entry = (LsEntry) obj;
87                         SftpATTRS attrs = entry.getAttrs();
88                         return new BasicResource(path, true, attrs.getSize(), attrs.getMTime() * 1000, false);
89                     }
90                 }
91             }
92         } catch (Exception JavaDoc e) {
93             Message.debug("reolving resource error: "+e.getMessage());
94             //silent fail, return unexisting resource
95
}
96         return new BasicResource(path, false, 0, 0, false);
97     }
98
99     public InputStream JavaDoc openStream(SFTPResource resource) throws IOException JavaDoc {
100         ChannelSftp c = getSftpChannel(resource.getName());
101         try {
102             return c.get(resource.getName());
103         } catch (SftpException e) {
104             e.printStackTrace();
105             IOException JavaDoc ex = new IOException JavaDoc("impossible to open stream for "+resource+" on "+getHost()+(e.getMessage() != null?": " + e.getMessage():""));
106             ex.initCause(e);
107             throw ex;
108         }
109     }
110
111     public void get(String JavaDoc source, File JavaDoc destination) throws IOException JavaDoc {
112         fireTransferInitiated(getResource(source), TransferEvent.REQUEST_GET);
113         ChannelSftp c = getSftpChannel(source);
114         try {
115             c.get(source, destination.getAbsolutePath(), new MyProgressMonitor());
116         } catch (SftpException e) {
117             e.printStackTrace();
118             IOException JavaDoc ex = new IOException JavaDoc("impossible to get "+source+" on "+getHost()+(e.getMessage() != null?": " + e.getMessage():""));
119             ex.initCause(e);
120             throw ex;
121         }
122     }
123
124     public void put(File JavaDoc source, String JavaDoc destination, boolean overwrite) throws IOException JavaDoc {
125         fireTransferInitiated(getResource(destination), TransferEvent.REQUEST_PUT);
126         ChannelSftp c = getSftpChannel(destination);
127         try {
128             if(!overwrite && checkExistence(destination, c))
129                 throw new IOException JavaDoc("destination file exists and overwrite == true");
130             if (destination.indexOf('/') != -1) {
131                 mkdirs(destination.substring(0, destination.lastIndexOf('/')),c);
132             }
133             c.put(source.getAbsolutePath(), destination, new MyProgressMonitor());
134         } catch (SftpException e) {
135             IOException JavaDoc ex = new IOException JavaDoc(e.getMessage());
136             ex.initCause(e);
137             throw ex;
138         }
139     }
140
141     private void mkdirs(String JavaDoc directory, ChannelSftp c) throws IOException JavaDoc, SftpException {
142         try {
143             SftpATTRS att = c.stat(directory);
144             if (att != null) {
145                 if (att.isDir()) {
146                     return;
147                 }
148             }
149         } catch (SftpException ex) {
150             if (directory.indexOf('/') != -1) {
151                 mkdirs(directory.substring(0, directory.lastIndexOf('/')),c);
152             }
153             c.mkdir(directory);
154         }
155     }
156
157
158     public List JavaDoc list(String JavaDoc parent) throws IOException JavaDoc {
159         try {
160             ChannelSftp c = getSftpChannel(parent);
161             Collection JavaDoc r = c.ls(parent);
162             if (r != null) {
163                 if (!parent.endsWith("/")) {
164                     parent = parent+"/";
165                 }
166                 List JavaDoc result = new ArrayList JavaDoc();
167                 for (Iterator JavaDoc iter = r.iterator(); iter.hasNext();) {
168                     Object JavaDoc obj=iter.next();
169                     if(obj instanceof LsEntry){
170                         LsEntry entry = (LsEntry) obj;
171                         if (".".equals(entry.getFilename()) || "..".equals(entry.getFilename())) {
172                             continue;
173                         }
174                         result.add(parent+entry.getFilename());
175                     }
176                 }
177                 return result;
178             }
179         } catch (Exception JavaDoc e) {
180             //silent fail, return null listing
181
}
182         return null;
183     }
184
185     /**
186      * Checks the existence for a remote file
187      * @param file to check
188      * @param channel to use
189      * @returns true if file exists, false otherwise
190      * @throws IOException
191      * @throws SftpException
192      */

193     private boolean checkExistence(String JavaDoc file, ChannelSftp channel) throws IOException JavaDoc, SftpException {
194         try {
195             return channel.stat(file) != null;
196         } catch (SftpException ex) {
197             return false;
198         }
199     }
200     
201     /**
202      * Establish the connection to the server if not yet connected, and listen to ivy events
203      * for closing connection when resolve is finished.
204      *
205      * Not meant to be used in multi threaded environment.
206      *
207      * @return the ChannelSftp with which a connection is established
208      * @throws IOException if any connection problem occurs
209      */

210     private ChannelSftp getSftpChannel(String JavaDoc pathOrUri) throws IOException JavaDoc {
211         Session session = getSession(pathOrUri);
212         String JavaDoc host = session.getHost();
213         ChannelSftp channel = SshCache.getInstance().getChannelSftp(session);
214         if(channel == null) {
215             try {
216                 channel = (ChannelSftp) session.openChannel("sftp");
217                 channel.connect();
218                 Message.verbose(":: SFTP :: connected to "+host+"!");
219                 SshCache.getInstance().attachChannelSftp(session,channel);
220             } catch (JSchException e) {
221                 IOException JavaDoc ex = new IOException JavaDoc(e.getMessage());
222                 ex.initCause(e);
223                 throw ex;
224             }
225         }
226         return channel;
227     }
228
229     protected String JavaDoc getRepositoryScheme() {
230         // use the Resolver type name here?
231
// would be nice if it would be static, so we could use SFTPResolver.getTypeName()
232
return "sftp";
233     }
234 }
235
Popular Tags