comparison src/org/tmatesoft/hg/repo/HgRemoteRepository.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
25 import java.io.IOException; 25 import java.io.IOException;
26 import java.io.InputStream; 26 import java.io.InputStream;
27 import java.io.InputStreamReader; 27 import java.io.InputStreamReader;
28 import java.io.OutputStream; 28 import java.io.OutputStream;
29 import java.io.StreamTokenizer; 29 import java.io.StreamTokenizer;
30 import java.net.URI;
30 import java.util.ArrayList; 31 import java.util.ArrayList;
31 import java.util.Arrays; 32 import java.util.Arrays;
32 import java.util.Collection; 33 import java.util.Collection;
33 import java.util.Collections; 34 import java.util.Collections;
34 import java.util.HashSet; 35 import java.util.HashSet;
37 import java.util.LinkedList; 38 import java.util.LinkedList;
38 import java.util.List; 39 import java.util.List;
39 import java.util.Map; 40 import java.util.Map;
40 import java.util.Set; 41 import java.util.Set;
41 42
43 import org.tmatesoft.hg.auth.HgAuthFailedException;
42 import org.tmatesoft.hg.core.HgBadArgumentException; 44 import org.tmatesoft.hg.core.HgBadArgumentException;
43 import org.tmatesoft.hg.core.HgIOException; 45 import org.tmatesoft.hg.core.HgIOException;
44 import org.tmatesoft.hg.core.HgRemoteConnectionException; 46 import org.tmatesoft.hg.core.HgRemoteConnectionException;
45 import org.tmatesoft.hg.core.HgRepositoryNotFoundException; 47 import org.tmatesoft.hg.core.HgRepositoryNotFoundException;
46 import org.tmatesoft.hg.core.Nodeid; 48 import org.tmatesoft.hg.core.Nodeid;
47 import org.tmatesoft.hg.core.SessionContext; 49 import org.tmatesoft.hg.core.SessionContext;
48 import org.tmatesoft.hg.internal.BundleSerializer; 50 import org.tmatesoft.hg.internal.BundleSerializer;
49 import org.tmatesoft.hg.internal.DataSerializer; 51 import org.tmatesoft.hg.internal.DataSerializer;
50 import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer; 52 import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer;
51 import org.tmatesoft.hg.internal.EncodingHelper; 53 import org.tmatesoft.hg.internal.EncodingHelper;
54 import org.tmatesoft.hg.internal.Experimental;
52 import org.tmatesoft.hg.internal.FileUtils; 55 import org.tmatesoft.hg.internal.FileUtils;
53 import org.tmatesoft.hg.internal.Internals; 56 import org.tmatesoft.hg.internal.Internals;
54 import org.tmatesoft.hg.internal.PropertyMarshal; 57 import org.tmatesoft.hg.internal.PropertyMarshal;
55 import org.tmatesoft.hg.internal.remote.Connector; 58 import org.tmatesoft.hg.internal.remote.Connector;
56 import org.tmatesoft.hg.internal.remote.RemoteConnectorDescriptor; 59 import org.tmatesoft.hg.internal.remote.RemoteConnectorDescriptor;
57 import org.tmatesoft.hg.repo.HgLookup.RemoteDescriptor; 60 import org.tmatesoft.hg.util.Adaptable;
58 import org.tmatesoft.hg.util.LogFacility.Severity; 61 import org.tmatesoft.hg.util.LogFacility.Severity;
59 import org.tmatesoft.hg.util.Outcome; 62 import org.tmatesoft.hg.util.Outcome;
60 import org.tmatesoft.hg.util.Pair; 63 import org.tmatesoft.hg.util.Pair;
61 64
62 /** 65 /**
75 private final SessionContext sessionContext; 78 private final SessionContext sessionContext;
76 private Set<String> remoteCapabilities; 79 private Set<String> remoteCapabilities;
77 private Connector remote; 80 private Connector remote;
78 81
79 HgRemoteRepository(SessionContext ctx, RemoteDescriptor rd) throws HgBadArgumentException { 82 HgRemoteRepository(SessionContext ctx, RemoteDescriptor rd) throws HgBadArgumentException {
80 if (false == rd instanceof RemoteConnectorDescriptor) { 83 RemoteConnectorDescriptor rcd = Adaptable.Factory.getAdapter(rd, RemoteConnectorDescriptor.class, null);
84 if (rcd == null) {
81 throw new IllegalArgumentException(String.format("Present implementation supports remote connections via %s only", Connector.class.getName())); 85 throw new IllegalArgumentException(String.format("Present implementation supports remote connections via %s only", Connector.class.getName()));
82 } 86 }
83 sessionContext = ctx; 87 sessionContext = ctx;
84 debug = new PropertyMarshal(ctx).getBoolean("hg4j.remote.debug", false); 88 debug = new PropertyMarshal(ctx).getBoolean("hg4j.remote.debug", false);
85 remote = ((RemoteConnectorDescriptor) rd).createConnector(); 89 remote = rcd.createConnector();
86 remote.init(rd.getURI(), ctx, null); 90 remote.init(rd /*sic! pass original*/, ctx, null);
87 } 91 }
88 92
89 public boolean isInvalid() throws HgRemoteConnectionException { 93 public boolean isInvalid() throws HgRemoteConnectionException {
90 initCapabilities(); 94 initCapabilities();
91 return remoteCapabilities.isEmpty(); 95 return remoteCapabilities.isEmpty();
367 371
368 private void initCapabilities() throws HgRemoteConnectionException { 372 private void initCapabilities() throws HgRemoteConnectionException {
369 if (remoteCapabilities != null) { 373 if (remoteCapabilities != null) {
370 return; 374 return;
371 } 375 }
372 remote.connect(); 376 try {
377 remote.connect();
378 } catch (HgAuthFailedException ex) {
379 throw new HgRemoteConnectionException("Failed to authenticate", ex).setServerInfo(remote.getServerLocation());
380 }
373 try { 381 try {
374 remote.sessionBegin(); 382 remote.sessionBegin();
375 String capsLine = remote.getCapabilities(); 383 String capsLine = remote.getCapabilities();
376 String[] caps = capsLine.split("\\s"); 384 String[] caps = capsLine.split("\\s");
377 remoteCapabilities = new HashSet<String>(Arrays.asList(caps)); 385 remoteCapabilities = new HashSet<String>(Arrays.asList(caps));
538 */ 546 */
539 public boolean isPublishingServer() { 547 public boolean isPublishingServer() {
540 return pub; 548 return pub;
541 } 549 }
542 } 550 }
551
552 /**
553 * Session context ({@link SessionContext#getRemoteDescriptor(URI)} gives descriptor of remote when asked.
554 * Clients may supply own descriptors e.g. if need to pass extra information into Authenticator.
555 * Present implementation of {@link HgRemoteRepository} will be happy with any {@link RemoteDescriptor} subclass
556 * as long as it's {@link Adaptable adaptable} to {@link RemoteConnectorDescriptor}
557 * @since 1.2
558 */
559 @Experimental(reason="Provisional API. Work in progress")
560 public interface RemoteDescriptor {
561 /**
562 * @return remote location, never <code>null</code>
563 */
564 URI getURI();
565 }
543 } 566 }