comparison src/org/tmatesoft/hg/internal/remote/HttpConnector.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
14 * the terms of a license other than GNU General Public License 14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com 15 * contact TMate Software at support@hg4j.com
16 */ 16 */
17 package org.tmatesoft.hg.internal.remote; 17 package org.tmatesoft.hg.internal.remote;
18 18
19 import static org.tmatesoft.hg.util.LogFacility.Severity.Info;
20
21 import java.io.BufferedReader; 19 import java.io.BufferedReader;
22 import java.io.ByteArrayInputStream; 20 import java.io.ByteArrayInputStream;
23 import java.io.FilterOutputStream; 21 import java.io.FilterOutputStream;
24 import java.io.IOException; 22 import java.io.IOException;
25 import java.io.InputStream; 23 import java.io.InputStream;
26 import java.io.InputStreamReader; 24 import java.io.InputStreamReader;
27 import java.io.OutputStream; 25 import java.io.OutputStream;
28 import java.io.SequenceInputStream; 26 import java.io.SequenceInputStream;
29 import java.net.HttpURLConnection; 27 import java.net.HttpURLConnection;
30 import java.net.MalformedURLException; 28 import java.net.MalformedURLException;
31 import java.net.URI;
32 import java.net.URL; 29 import java.net.URL;
33 import java.net.URLConnection; 30 import java.net.URLConnection;
34 import java.security.cert.CertificateException;
35 import java.security.cert.X509Certificate;
36 import java.util.Collection; 31 import java.util.Collection;
37 import java.util.List; 32 import java.util.List;
38 import java.util.Map; 33 import java.util.Map;
39 import java.util.prefs.BackingStoreException; 34
40 import java.util.prefs.Preferences; 35 import org.tmatesoft.hg.auth.HgAuthFailedException;
41 36 import org.tmatesoft.hg.auth.HgAuthenticator;
42 import javax.net.ssl.HttpsURLConnection;
43 import javax.net.ssl.SSLContext;
44 import javax.net.ssl.TrustManager;
45 import javax.net.ssl.X509TrustManager;
46
47 import org.tmatesoft.hg.core.HgRemoteConnectionException; 37 import org.tmatesoft.hg.core.HgRemoteConnectionException;
48 import org.tmatesoft.hg.core.Nodeid; 38 import org.tmatesoft.hg.core.Nodeid;
49 import org.tmatesoft.hg.core.SessionContext; 39 import org.tmatesoft.hg.core.SessionContext;
50 import org.tmatesoft.hg.internal.PropertyMarshal; 40 import org.tmatesoft.hg.internal.PropertyMarshal;
51 import org.tmatesoft.hg.repo.HgRemoteRepository.Range; 41 import org.tmatesoft.hg.repo.HgRemoteRepository.Range;
42 import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteDescriptor;
52 import org.tmatesoft.hg.repo.HgRuntimeException; 43 import org.tmatesoft.hg.repo.HgRuntimeException;
53 44
54 /** 45 /**
55 * 46 *
56 * @author Artem Tikhomirov 47 * @author Artem Tikhomirov
57 * @author TMate Software Ltd. 48 * @author TMate Software Ltd.
58 */ 49 */
59 public class HttpConnector implements Connector { 50 public class HttpConnector extends ConnectorBase {
60 private URI uri; 51 private RemoteDescriptor rd;
61 private URL url; 52 private URL url;
62 private SSLContext sslContext;
63 private String authInfo;
64 private boolean debug; 53 private boolean debug;
65 private SessionContext sessionCtx; 54 private SessionContext sessionCtx;
66 // 55 //
67 private HttpURLConnection conn; 56 private HttpURLConnection conn;
68 57 private HttpAuthMethod authMediator;
69 public void init(URI uri, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException { 58
70 this.uri = uri; 59 public void init(RemoteDescriptor remote, SessionContext sessionContext, Object globalConfig) throws HgRuntimeException {
60 rd = remote;
61 setURI(remote.getURI());
71 sessionCtx = sessionContext; 62 sessionCtx = sessionContext;
72 debug = new PropertyMarshal(sessionCtx).getBoolean("hg4j.remote.debug", false); 63 debug = new PropertyMarshal(sessionContext).getBoolean("hg4j.remote.debug", false);
73 if (uri.getUserInfo() != null) { 64 }
74 String ai = null; 65
66 public void connect() throws HgAuthFailedException, HgRemoteConnectionException, HgRuntimeException {
67 try {
68 url = uri.toURL();
69 } catch (MalformedURLException ex) {
70 throw new HgRemoteConnectionException("Bad URL", ex);
71 }
72 authMediator = new HttpAuthMethod(sessionCtx, url);
73 authenticateClient();
74 }
75
76 private void authenticateClient() throws HgAuthFailedException {
77 String userInfo = url.getUserInfo();
78 if (userInfo != null) {
75 try { 79 try {
76 // Hack to get Base64-encoded credentials 80 authMediator.tryWithUserInfo(userInfo);
77 Preferences tempNode = Preferences.userRoot().node("xxx"); 81 } catch (HgAuthFailedException ex) {
78 tempNode.putByteArray("xxx", uri.getUserInfo().getBytes()); 82 // FALL THROUGH to try Authenticator
79 ai = tempNode.get("xxx", null); 83 }
80 tempNode.removeNode(); 84 }
81 } catch (BackingStoreException ex) { 85 HgAuthenticator auth = sessionCtx.getAuthenticator(rd);
82 sessionContext.getLog().dump(getClass(), Info, ex, null); 86 auth.authenticate(rd, authMediator);
83 // IGNORE
84 }
85 authInfo = ai;
86 } else {
87 authInfo = null;
88 }
89 }
90
91 public void connect() throws HgRemoteConnectionException, HgRuntimeException {
92 try {
93 url = uri.toURL();
94 } catch (MalformedURLException ex) {
95 throw new HgRemoteConnectionException("Bad URL", ex);
96 }
97 if ("https".equals(url.getProtocol())) {
98 try {
99 sslContext = SSLContext.getInstance("SSL");
100 class TrustEveryone implements X509TrustManager {
101 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
102 if (debug) {
103 System.out.println("checkClientTrusted:" + authType);
104 }
105 }
106 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
107 if (debug) {
108 System.out.println("checkServerTrusted:" + authType);
109 }
110 }
111 public X509Certificate[] getAcceptedIssuers() {
112 return new X509Certificate[0];
113 }
114 };
115 sslContext.init(null, new TrustManager[] { new TrustEveryone() }, null);
116 } catch (Exception ex) {
117 throw new HgRemoteConnectionException("Can't initialize secure connection", ex);
118 }
119 } else {
120 sslContext = null;
121 }
122 } 87 }
123 88
124 public void disconnect() throws HgRemoteConnectionException, HgRuntimeException { 89 public void disconnect() throws HgRemoteConnectionException, HgRuntimeException {
125 // TODO Auto-generated method stub 90 // TODO Auto-generated method stub
126 91
136 conn.disconnect(); 101 conn.disconnect();
137 conn = null; 102 conn = null;
138 } 103 }
139 } 104 }
140 105
141 public String getServerLocation() {
142 if (uri.getUserInfo() == null) {
143 return uri.toString();
144 }
145 if (uri.getPort() != -1) {
146 return String.format("%s://%s:%d%s", uri.getScheme(), uri.getHost(), uri.getPort(), uri.getPath());
147 } else {
148 return String.format("%s://%s%s", uri.getScheme(), uri.getHost(), uri.getPath());
149 }
150 }
151
152 public String getCapabilities() throws HgRemoteConnectionException { 106 public String getCapabilities() throws HgRemoteConnectionException {
153 // say hello to server, check response 107 // say hello to server, check response
154 try { 108 try {
155 URL u = new URL(url, url.getPath() + "?cmd=hello"); 109 URL u = new URL(url, url.getPath() + "?cmd=hello");
156 HttpURLConnection c = setupConnection(u.openConnection()); 110 HttpURLConnection c = setupConnection(u.openConnection());
365 } 319 }
366 320
367 private HttpURLConnection setupConnection(URLConnection urlConnection) { 321 private HttpURLConnection setupConnection(URLConnection urlConnection) {
368 urlConnection.setRequestProperty("User-Agent", "hg4j/1.0.0"); 322 urlConnection.setRequestProperty("User-Agent", "hg4j/1.0.0");
369 urlConnection.addRequestProperty("Accept", "application/mercurial-0.1"); 323 urlConnection.addRequestProperty("Accept", "application/mercurial-0.1");
370 if (authInfo != null) { 324 return authMediator.setupConnection((HttpURLConnection) urlConnection);
371 urlConnection.addRequestProperty("Authorization", "Basic " + authInfo);
372 }
373 if (sslContext != null) {
374 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslContext.getSocketFactory());
375 }
376 return (HttpURLConnection) urlConnection;
377 } 325 }
378 326
379 private StringBuilder appendNodeidListArgument(String key, List<Nodeid> values, StringBuilder sb) { 327 private StringBuilder appendNodeidListArgument(String key, List<Nodeid> values, StringBuilder sb) {
380 if (sb == null) { 328 if (sb == null) {
381 sb = new StringBuilder(20 + values.size() * 41); 329 sb = new StringBuilder(20 + values.size() * 41);