KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > jayasoft > ivy > repository > ssh > SshCache


1 package fr.jayasoft.ivy.repository.ssh;
2
3 import java.io.File JavaDoc;
4 import java.io.IOException JavaDoc;
5 import java.util.HashMap JavaDoc;
6 import java.util.Map JavaDoc;
7
8 import com.jcraft.jsch.ChannelSftp;
9 import com.jcraft.jsch.JSch;
10 import com.jcraft.jsch.JSchException;
11 import com.jcraft.jsch.Session;
12 import com.jcraft.jsch.UserInfo;
13
14 import fr.jayasoft.ivy.IvyContext;
15 import fr.jayasoft.ivy.event.IvyEvent;
16 import fr.jayasoft.ivy.event.IvyListener;
17 import fr.jayasoft.ivy.event.resolve.EndResolveEvent;
18 import fr.jayasoft.ivy.util.Credentials;
19 import fr.jayasoft.ivy.util.CredentialsUtil;
20 import fr.jayasoft.ivy.util.Message;
21
22 /**
23  * a class to cache SSH Connections and Channel for the SSH Repository
24  * each session is defined by connecting user / host / port
25  * two maps are used to find cache entries
26  * one map is using the above keys, the other
27  * uses the session itself
28  */

29 public class SshCache {
30     
31     private SshCache() {};
32     
33     private static SshCache instance = new SshCache();
34     
35     public static SshCache getInstance() {
36         return instance;
37     }
38     
39     private class Entry {
40         private Session session = null;
41         private ChannelSftp channelSftp = null;
42         private String JavaDoc host = null;
43         private String JavaDoc user = null;
44         private int port = 22;
45         
46         /**
47          * @return the host
48          */

49         public String JavaDoc getHost() {
50             return host;
51         }
52
53         /**
54          * @return the port
55          */

56         public int getPort() {
57             return port;
58         }
59
60         /**
61          * @return the user
62          */

63         public String JavaDoc getUser() {
64             return user;
65         }
66
67         public Entry(Session newSession, String JavaDoc newUser, String JavaDoc newHost, int newPort) {
68             session = newSession;
69             host = newHost;
70             user = newUser;
71             port = newPort;
72             IvyContext.getContext().getIvy().addIvyListener(new IvyListener() {
73                 public void progress(IvyEvent event) {
74                     event.getSource().removeIvyListener(this);
75                     clearSession(session);
76                 }
77             }, EndResolveEvent.NAME);
78         }
79
80         /**
81          * attach an sftp channel to this cache entry
82          * @param channelSftp to attach
83          */

84         public void setChannelSftp(ChannelSftp newChannel) {
85             if(channelSftp != null && newChannel != null )
86                 throw new IllegalStateException JavaDoc("Only one sftp channelSftp per session allowed");
87             this.channelSftp = newChannel;
88         }
89         
90         /**
91          * @return the attached sftp channel
92          */

93         public ChannelSftp getChannelSftp() {
94             return channelSftp;
95         }
96         
97         /**
98          * @return the session
99          */

100         private Session getSession() {
101             return session;
102         }
103
104         /**
105          * remove channelSftp and disconnect if necessary
106          */

107         public void releaseChannelSftp() {
108             if(channelSftp != null) {
109                 if(channelSftp.isConnected()) {
110                     Message.verbose(":: SFTP :: closing sftp connection from "+host+"...");
111                     channelSftp.disconnect();
112                     channelSftp = null;
113                     Message.verbose(":: SFTP :: sftp connection closed from "+host);
114                 }
115             }
116         }
117     }
118     /**
119      * key is username / host / port
120      * @see SshCache.createCacheKey() for details
121      */

122     private Map JavaDoc uriCacheMap = new HashMap JavaDoc();
123     /**
124      * key is the session itself
125      */

126     private Map JavaDoc sessionCacheMap = new HashMap JavaDoc();
127     
128     /**
129      * retrieves a session entry for a given hostname from the cache
130      * @param hostname to retrieve session for
131      * @return null or the existing entry
132      */

133     private Entry getCacheEntry(String JavaDoc user, String JavaDoc host, int port) {
134         return (Entry)uriCacheMap.get(createCacheKey(user, host, port));
135     }
136
137     /**
138      * Creates a cobined cache key from the given key parts
139      * @param user name of the user
140      * @param host of the connection
141      * @param port of the connection
142      * @return key for the cache
143      */

144     private static String JavaDoc createCacheKey(String JavaDoc user, String JavaDoc host, int port) {
145         String JavaDoc portToUse = "22";
146         if(port != -1 && port != 22)
147             portToUse = Integer.toString(port);
148         return user.toLowerCase().trim()+"@"+host.toLowerCase().trim()+":"+portToUse;
149     }
150     
151     /**
152      * retrieves a session entry for a given session from the cache
153      * @param session to retrieve cache entry for
154      * @return null or the existing entry
155      */

156     private Entry getCacheEntry(Session session) {
157         return (Entry)sessionCacheMap.get(session);
158     }
159
160     /**
161      * Sets a session to a given combined key into the cache
162      * If an old session object already exists, close and remove it
163      * @param user of the session
164      * @param host of the session
165      * @param port of the session
166      * @param session Session to save
167      */

168     private void setSession(String JavaDoc user, String JavaDoc host, int port, Session newSession) {
169         Entry entry = (Entry)uriCacheMap.get(createCacheKey(user, host, port));
170         Session oldSession = null;
171         if(entry != null)
172             oldSession = entry.getSession();
173         if(oldSession != null && !oldSession.equals(newSession) &&
174            oldSession.isConnected()) {
175             entry.releaseChannelSftp();
176             String JavaDoc oldhost = oldSession.getHost();
177             Message.verbose(":: SSH :: closing ssh connection from "+oldhost+"...");
178             oldSession.disconnect();
179             Message.verbose(":: SSH :: ssh connection closed from "+oldhost);
180         }
181         if((newSession == null) && (entry != null)) {
182             uriCacheMap.remove(createCacheKey(user, host, port));
183             if(entry.getSession() != null)
184                 sessionCacheMap.remove(entry.getSession());
185         } else {
186             Entry newEntry = new Entry(newSession,user,host,port);
187             uriCacheMap.put(createCacheKey(user, host, port), newEntry);
188             sessionCacheMap.put(newSession, newEntry);
189         }
190     }
191
192     /**
193      * discardes session entries from the cache
194      * @param session to clear
195      */

196     public void clearSession(Session session) {
197         Entry entry = (Entry)sessionCacheMap.get(session);
198         if(entry != null)
199             setSession(entry.getUser(), entry.getHost(), entry.getPort(), null);
200     }
201     
202     /**
203      * retrieves an sftp channel from the cache
204      * @param host to connect to
205      * @return channelSftp or null if not successful (channel not existent or dead)
206      */

207     public ChannelSftp getChannelSftp(Session session) throws IOException JavaDoc {
208         ChannelSftp channel = null;
209         Entry entry = getCacheEntry(session);
210         if(entry != null) {
211             channel = entry.getChannelSftp();
212             if(channel != null && !channel.isConnected()) {
213                 entry.releaseChannelSftp();
214                 channel = null;
215             }
216         }
217         return channel;
218     }
219     
220     /**
221      * attaches a channelSftp to an existing session cache entry
222      * @param session to attach the channel to
223      * @param channelSftp channel to attach
224      */

225     public void attachChannelSftp(Session session, ChannelSftp channel) {
226         Entry entry = getCacheEntry(session);
227         if(entry == null)
228             throw new IllegalArgumentException JavaDoc("No entry for "+session+" in the cache");
229         entry.setChannelSftp(channel);
230     }
231     
232     /**
233      * Gets a session from the cache or establishes a new session if necessary
234      * @param username for the session to use
235      * @param host to connect to
236      * @param port to use for session (-1 == use standard port)
237      * @param password to use for authentication (optional)
238      * @param pemFile File to use for public key authentication
239      * @param pemPassword to use for accessing the pemFile (optional)
240      * @param passFile to store credentials
241      * @return session or null if not successful
242      */

243     public Session getSession(String JavaDoc host,
244                               int port,
245                               String JavaDoc username,
246                               String JavaDoc userPassword,
247                               File JavaDoc pemFile,
248                               String JavaDoc pemPassword,
249                               File JavaDoc passFile) throws IOException JavaDoc {
250         Entry entry = getCacheEntry(username, host, port);
251         Session session = null;
252         if(entry != null)
253             session = entry.getSession();
254         if(session == null || !session.isConnected()) {
255             Message.verbose(":: SSH :: connecting to "+host+"...");
256             try {
257                 JSch jsch=new JSch();
258                 if(port != -1)
259                     session = jsch.getSession(username,host,port);
260                 else
261                     session = jsch.getSession(username,host);
262                 if(pemFile != null) {
263                     jsch.addIdentity(pemFile.getAbsolutePath(), pemPassword);
264                 }
265                 session.setUserInfo(new cfUserInfo(host,username,userPassword,pemFile,pemPassword,passFile));
266                 session.connect();
267                 Message.verbose(":: SSH :: connected to "+host+"!");
268                 setSession(username, host, port, session);
269             } catch (JSchException e) {
270                 if (passFile.exists()) {
271                     passFile.delete();
272                 }
273                 IOException JavaDoc ex = new IOException JavaDoc(e.getMessage());
274                 ex.initCause(e);
275                 throw ex;
276             }
277         }
278         return session;
279     }
280     
281     /**
282      * feeds in password silently into JSch
283      */

284     private static class cfUserInfo implements UserInfo {
285         
286         private String JavaDoc userPassword;
287         private String JavaDoc pemPassword;
288         private String JavaDoc userName;
289         private final File JavaDoc pemFile;
290         private final String JavaDoc host;
291         private final File JavaDoc passfile;
292         
293         public cfUserInfo(String JavaDoc host, String JavaDoc userName, String JavaDoc userPassword, File JavaDoc pemFile, String JavaDoc pemPassword, File JavaDoc passfile) {
294             this.userPassword = userPassword;
295             this.pemPassword = pemPassword;
296             this.host = host;
297             this.passfile = passfile;
298             this.userName = userName;
299             this.pemFile = pemFile;
300         }
301         
302         public void showMessage(String JavaDoc message) {
303             Message.info(message);
304         }
305
306         public boolean promptYesNo(String JavaDoc message) {
307             return true;
308         }
309
310         public boolean promptPassword(String JavaDoc message) {
311             return true;
312         }
313
314         public boolean promptPassphrase(String JavaDoc message) {
315             return true;
316         }
317
318         public String JavaDoc getPassword() {
319             if(userPassword == null) {
320                 Credentials c = CredentialsUtil.promptCredentials(new Credentials(null, host, userName, userPassword), passfile);
321                 if (c != null) {
322                     userName = c.getUserName();
323                     userPassword = c.getPasswd();
324                 }
325             }
326             return userPassword;
327         }
328
329         public String JavaDoc getPassphrase() {
330             if(pemPassword == null && pemFile != null) {
331                 Credentials c = CredentialsUtil.promptCredentials(new Credentials(null, pemFile.getAbsolutePath(), userName, pemPassword), passfile);
332                 if (c != null) {
333                     userName = c.getUserName();
334                     pemPassword = c.getPasswd();
335                 }
336             }
337             return pemPassword;
338         }
339     }
340 }
341
Popular Tags