Mercurial > jhg
comparison src/org/tmatesoft/hg/internal/remote/SshConnector.java @ 699:a483b2b68a2e
Provisional APIs and respective implementation for http, https and ssh remote repositories
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 08 Aug 2013 19:18:50 +0200 |
parents | 822f3a83ff57 |
children |
comparison
equal
deleted
inserted
replaced
698:822f3a83ff57 | 699:a483b2b68a2e |
---|---|
18 | 18 |
19 import java.io.BufferedReader; | 19 import java.io.BufferedReader; |
20 import java.io.ByteArrayInputStream; | 20 import java.io.ByteArrayInputStream; |
21 import java.io.Closeable; | 21 import java.io.Closeable; |
22 import java.io.EOFException; | 22 import java.io.EOFException; |
23 import java.io.File; | |
24 import java.io.FilterInputStream; | 23 import java.io.FilterInputStream; |
25 import java.io.FilterOutputStream; | 24 import java.io.FilterOutputStream; |
26 import java.io.IOException; | 25 import java.io.IOException; |
27 import java.io.InputStream; | 26 import java.io.InputStream; |
28 import java.io.InputStreamReader; | 27 import java.io.InputStreamReader; |
29 import java.io.OutputStream; | 28 import java.io.OutputStream; |
30 import java.io.SequenceInputStream; | 29 import java.io.SequenceInputStream; |
31 import java.net.URI; | |
32 import java.util.ArrayList; | 30 import java.util.ArrayList; |
33 import java.util.Collection; | 31 import java.util.Collection; |
34 import java.util.Collections; | 32 import java.util.Collections; |
35 import java.util.List; | 33 import java.util.List; |
36 | 34 |
35 import org.tmatesoft.hg.auth.HgAuthFailedException; | |
36 import org.tmatesoft.hg.auth.HgAuthenticator; | |
37 import org.tmatesoft.hg.core.HgRemoteConnectionException; | 37 import org.tmatesoft.hg.core.HgRemoteConnectionException; |
38 import org.tmatesoft.hg.core.Nodeid; | 38 import org.tmatesoft.hg.core.Nodeid; |
39 import org.tmatesoft.hg.core.SessionContext; | 39 import org.tmatesoft.hg.core.SessionContext; |
40 import org.tmatesoft.hg.repo.HgRemoteRepository.Range; | 40 import org.tmatesoft.hg.repo.HgRemoteRepository.Range; |
41 import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteDescriptor; | |
41 import org.tmatesoft.hg.repo.HgRuntimeException; | 42 import org.tmatesoft.hg.repo.HgRuntimeException; |
42 import org.tmatesoft.hg.util.LogFacility.Severity; | 43 import org.tmatesoft.hg.util.LogFacility.Severity; |
43 | 44 |
44 import com.trilead.ssh2.Connection; | 45 import com.trilead.ssh2.Connection; |
45 import com.trilead.ssh2.ConnectionInfo; | |
46 import com.trilead.ssh2.Session; | 46 import com.trilead.ssh2.Session; |
47 import com.trilead.ssh2.StreamGobbler; | 47 import com.trilead.ssh2.StreamGobbler; |
48 | 48 |
49 /** | 49 /** |
50 * Remote repository via SSH | 50 * Remote repository via SSH |
51 * | 51 * |
52 * @author Artem Tikhomirov | 52 * @author Artem Tikhomirov |
53 * @author TMate Software Ltd. | 53 * @author TMate Software Ltd. |
54 */ | 54 */ |
55 public class SshConnector implements Connector { | 55 public class SshConnector extends ConnectorBase { |
56 private RemoteDescriptor rd; | |
56 private SessionContext sessionCtx; | 57 private SessionContext sessionCtx; |
57 private URI uri; | |
58 private Connection conn; | 58 private Connection conn; |
59 private Session session; | 59 private Session session; |
60 private int sessionUse; | 60 private int sessionUse; |
61 | 61 |
62 private StreamGobbler remoteErr, remoteOut; | 62 private StreamGobbler remoteErr, remoteOut; |
63 private OutputStream remoteIn; | 63 private OutputStream remoteIn; |
64 | 64 |
65 public void init(URI uri, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException { | 65 public void init(RemoteDescriptor remote, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException { |
66 rd = remote; | |
66 sessionCtx = sessionContext; | 67 sessionCtx = sessionContext; |
67 this.uri = uri; | 68 setURI(remote.getURI()); |
68 } | 69 } |
69 | 70 |
70 public void connect() throws HgRemoteConnectionException, HgRuntimeException { | 71 public void connect() throws HgAuthFailedException, HgRemoteConnectionException, HgRuntimeException { |
71 try { | 72 try { |
72 conn = new Connection(uri.getHost(), uri.getPort() == -1 ? 22 : uri.getPort()); | 73 conn = new Connection(uri.getHost(), uri.getPort() == -1 ? 22 : uri.getPort()); |
73 conn.connect(); | 74 conn.connect(); |
74 } catch (IOException ex) { | 75 authenticateClient(); |
75 throw new HgRemoteConnectionException("Failed to establish connection"); | 76 } catch (IOException ex) { |
76 } | 77 throw new HgRemoteConnectionException("Failed to establish connection").setServerInfo(getServerLocation()); |
77 try { | 78 } |
78 conn.authenticateWithPublicKey(System.getProperty("user.name"), new File(System.getProperty("user.home"), ".ssh/id_rsa"), null); | 79 } |
79 ConnectionInfo ci = conn.getConnectionInfo(); | 80 |
80 System.out.printf("%s %s %s %d %s %s %s\n", ci.clientToServerCryptoAlgorithm, ci.clientToServerMACAlgorithm, ci.keyExchangeAlgorithm, ci.keyExchangeCounter, ci.serverHostKeyAlgorithm, ci.serverToClientCryptoAlgorithm, ci.serverToClientMACAlgorithm); | 81 private void authenticateClient() throws HgAuthFailedException { |
81 } catch (IOException ex) { | 82 SshAuthMethod m = new SshAuthMethod(conn); |
82 throw new HgRemoteConnectionException("Failed to authenticate", ex).setServerInfo(getServerLocation()); | 83 if (uri.getUserInfo() != null) { |
83 } | 84 try { |
85 m.tryWithUserInfo(uri.getUserInfo()); | |
86 return; | |
87 } catch (HgAuthFailedException ex) { | |
88 // FALL-THROUGH to try with Authenticator | |
89 } | |
90 } | |
91 HgAuthenticator auth = sessionCtx.getAuthenticator(rd); | |
92 auth.authenticate(rd, m); | |
84 } | 93 } |
85 | 94 |
86 public void disconnect() throws HgRemoteConnectionException { | 95 public void disconnect() throws HgRemoteConnectionException { |
87 if (session != null) { | 96 if (session != null) { |
88 forceSessionClose(); | 97 doSessionClose(); |
89 } | 98 } |
90 if (conn != null) { | 99 if (conn != null) { |
91 conn.close(); | 100 conn.close(); |
92 conn = null; | 101 conn = null; |
93 } | 102 } |
117 assert session != null; | 126 assert session != null; |
118 if (sessionUse > 1) { | 127 if (sessionUse > 1) { |
119 sessionUse--; | 128 sessionUse--; |
120 return; | 129 return; |
121 } | 130 } |
122 forceSessionClose(); | 131 doSessionClose(); |
123 } | 132 } |
124 | 133 |
125 public String getServerLocation() { | |
126 return uri.toString(); // FIXME | |
127 } | |
128 | |
129 public String getCapabilities() throws HgRemoteConnectionException { | 134 public String getCapabilities() throws HgRemoteConnectionException { |
130 try { | 135 try { |
131 consume(remoteOut); | 136 consume(remoteOut); |
132 consume(remoteErr); | 137 consume(remoteErr); |
133 remoteIn.write(CMD_HELLO.getBytes()); | 138 remoteIn.write(CMD_HELLO.getBytes()); |
289 throw new IOException(String.format("Expected response length instead of %s", sb)); | 294 throw new IOException(String.format("Expected response length instead of %s", sb)); |
290 } | 295 } |
291 } | 296 } |
292 | 297 |
293 | 298 |
294 private void forceSessionClose() { | 299 private void doSessionClose() { |
295 if (session != null) { | 300 if (session != null) { |
296 closeQuietly(remoteErr); | 301 closeQuietly(remoteErr); |
297 closeQuietly(remoteOut); | 302 closeQuietly(remoteOut); |
298 remoteErr = remoteOut = null; | 303 remoteErr = remoteOut = null; |
299 closeQuietly(remoteIn); | 304 closeQuietly(remoteIn); |