KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ssh2 > CVSSSH2ServerConnection


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * Atsuhiko Yamanaka, JCraft,Inc. - initial API and implementation.
10  * IBM Corporation - ongoing maintenance
11  *******************************************************************************/

12 package org.eclipse.team.internal.ccvs.ssh2;
13 import java.io.*;
14 import java.net.NoRouteToHostException JavaDoc;
15 import java.net.UnknownHostException JavaDoc;
16
17 import org.eclipse.core.runtime.IProgressMonitor;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
20 import org.eclipse.team.internal.ccvs.core.IServerConnection;
21 import org.eclipse.team.internal.ccvs.core.connection.CVSAuthenticationException;
22 import org.eclipse.team.internal.ccvs.ssh.SSHServerConnection;
23 import org.eclipse.team.internal.core.streams.*;
24
25 import com.jcraft.jsch.*;
26
27 /**
28  * SSH2 connection method. Has the property of defaulting to SSH1 if the server
29  * doesn't support SSH2.
30  */

31 public class CVSSSH2ServerConnection implements IServerConnection {
32     private final class SSH2IOException extends IOException {
33         private static final long serialVersionUID = 1L;
34
35         private final JSchException e;
36
37         SSH2IOException(String JavaDoc s, JSchException e) {
38             super(s);
39             this.e = e;
40         }
41
42         public Throwable JavaDoc getCause() {
43             return e;
44         }
45     }
46     private static final String JavaDoc COMMAND = "cvs server"; //$NON-NLS-1$
47
private ICVSRepositoryLocation location;
48     private String JavaDoc password;
49     private InputStream inputStream;
50     private OutputStream outputStream;
51     private JSchSession session;
52     private Channel channel;
53     private IServerConnection ssh1;
54     
55     protected CVSSSH2ServerConnection(ICVSRepositoryLocation location, String JavaDoc password) {
56         this.location = location;
57         this.password = password;
58     }
59     public void close() throws IOException {
60         if (ssh1 != null) {
61             ssh1.close();
62             ssh1 = null;
63             return;
64         }
65         try {
66             if (inputStream != null) {
67                 try {
68                     inputStream.close();
69                 } catch (IOException e) {
70                     // Ignore I/O Exception on close
71
}
72             }
73         } finally {
74             try {
75                 if (outputStream != null) {
76                     try {
77                         outputStream.close();
78                     } catch (IOException e) {
79                         // Ignore I/O Exception on close
80
}
81                 }
82             } finally {
83                 if (channel != null)
84                     channel.disconnect();
85             }
86         }
87     }
88     public InputStream getInputStream() {
89         if (ssh1 != null) {
90             return ssh1.getInputStream();
91         }
92         return inputStream;
93     }
94     public OutputStream getOutputStream() {
95         if (ssh1 != null) {
96             return ssh1.getOutputStream();
97         }
98         return outputStream;
99     }
100     public void open(IProgressMonitor monitor) throws IOException, CVSAuthenticationException {
101         if (ssh1 != null) {
102             ssh1.open(monitor);
103             return;
104         }
105         monitor.subTask(NLS.bind(CVSSSH2Messages.CVSSSH2ServerConnection_open, new String JavaDoc[] { location.getHost() }));
106         monitor.worked(1);
107         internalOpen(monitor);
108     }
109     /**
110      * @param monitor
111      * @throws IOException
112      * @throws CVSAuthenticationException
113      */

114     private void internalOpen(IProgressMonitor monitor) throws IOException, CVSAuthenticationException {
115         try {
116             OutputStream channel_out = null;
117             InputStream channel_in = null;
118             boolean firstTime = true;
119             boolean tryAgain = false;
120             while (firstTime || tryAgain) {
121                 tryAgain = false; // reset the try again flag
122
session = JSchSession.getSession(location, location.getUsername(), password, location.getHost(), location.getPort(), monitor);
123                 channel = session.getSession().openChannel("exec"); //$NON-NLS-1$
124
((ChannelExec) channel).setCommand(COMMAND);
125                 channel_out = channel.getOutputStream();
126                 channel_in = channel.getInputStream();
127                 try {
128                     channel.connect();
129                 } catch (JSchException ee) {
130                     // This strange logic is here due to how the JSch client shares sessions.
131
// It is possible that we have obtained a session that thinks it is connected
132
// but is not. Channel connection only works if the session is connected so the
133
// above channel connect may fail because the session is down. For this reason,
134
// we want to retry if the connection fails.
135
try {
136                         if (firstTime && (isSessionDownError(ee) || isChannelNotOpenError(ee))) {
137                             tryAgain = true;
138                         }
139                         if (!tryAgain) {
140                             throw ee;
141                         }
142                     } finally {
143                         // Always dispose of the current session when a failure occurs so we can start from scratch
144
session.dispose();
145                     }
146                 }
147                 firstTime = false; // the first time is done
148
}
149             int timeout = location.getTimeout();
150             inputStream = new PollingInputStream(new TimeoutInputStream(new FilterInputStream(channel_in) {
151                         public void close() {
152                             // Don't close the underlying stream as it belongs to the session
153
}
154                     },
155                     8192 /*bufferSize*/, 1000 /*readTimeout*/, -1 /*closeTimeout*/, true /* growWhenFull */), timeout > 0 ? timeout : 1, monitor);
156             outputStream = new PollingOutputStream(new TimeoutOutputStream(new FilterOutputStream(channel_out) {
157                         public void close() {
158                             // Don't close the underlying stream as it belongs to the session
159
}
160                     },
161                     8192 /*buffersize*/, 1000 /*writeTimeout*/, 1000 /*closeTimeout*/), timeout > 0 ? timeout : 1, monitor);
162         } catch (final JSchException e) {
163             if (isSSH2Unsupported(e)) {
164                 ssh1 = new SSHServerConnection(location, password);
165                 if (ssh1 == null) {
166                     throw new SSH2IOException(e.toString(), e);
167                 }
168                 ssh1.open(monitor);
169             } else {
170                 String JavaDoc message = e.getMessage();
171                 if (JSchSession.isAuthenticationFailure(e)) {
172                     // Do not retry as the Jsh library has it's own retry logic
173
throw new CVSAuthenticationException(CVSSSH2Messages.CVSSSH2ServerConnection_0, CVSAuthenticationException.NO_RETRY,location, e);
174                 } else if (message.startsWith("Session.connect: ")) { //$NON-NLS-1$
175
// Jsh has messages formatted like "Session.connect: java.net.NoRouteToHostException: ..."
176
// Strip of the exception and try to convert it to a more meaningfull string
177
int start = message.indexOf(": ") + 1; //$NON-NLS-1$
178
if (start != -1) {
179                         int end = message.indexOf(": ", start); //$NON-NLS-1$
180
if (end != -1) {
181                             String JavaDoc exception = message.substring(start, end).trim();
182                             if (exception.indexOf("NoRouteToHostException") != -1) { //$NON-NLS-1$
183
message = NLS.bind(CVSSSH2Messages.CVSSSH2ServerConnection_1, new String JavaDoc[] { location.getHost() });
184                                 throw new NoRouteToHostException JavaDoc(message);
185                             } else if (exception.indexOf("java.net.UnknownHostException") != -1) { //$NON-NLS-1$
186
throw new UnknownHostException JavaDoc(location.getHost());
187                             } else {
188                                 message = message.substring(end + 1).trim();
189                             }
190                         }
191                     }
192                 }
193                 throw new SSH2IOException(message, e);
194             }
195         }
196     }
197     
198     private boolean isChannelNotOpenError(JSchException ee) {
199         return ee.getMessage().indexOf("channel is not opened") != -1; //$NON-NLS-1$
200
}
201     private boolean isSessionDownError(JSchException ee) {
202         return ee.getMessage().equals("session is down"); //$NON-NLS-1$
203
}
204     private boolean isSSH2Unsupported(JSchException e) {
205         return e.toString().indexOf("invalid server's version string") != -1; //$NON-NLS-1$
206
}
207 }
208
Popular Tags