comparison src/org/tmatesoft/hg/internal/remote/RemoteConnectorDescriptor.java @ 698:822f3a83ff57

in, out and clone tests pass for ssh repositories. Infrastructure to decouple HgRemoteRepository from specific Connector implementation
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 06 Aug 2013 21:18:33 +0200
parents
children a483b2b68a2e
comparison
equal deleted inserted replaced
697:24f4efedc9d5 698:822f3a83ff57
1 /*
2 * Copyright (c) 2013 TMate Software Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * For information on how to redistribute this software under
14 * the terms of a license other than GNU General Public License
15 * contact TMate Software at support@hg4j.com
16 */
17 package org.tmatesoft.hg.internal.remote;
18
19 import java.net.URI;
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.tmatesoft.hg.core.HgBadArgumentException;
24 import org.tmatesoft.hg.core.SessionContext;
25 import org.tmatesoft.hg.repo.HgLookup.Authenticator;
26 import org.tmatesoft.hg.repo.HgLookup.RemoteDescriptor;
27 import org.tmatesoft.hg.repo.HgRemoteRepository;
28 import org.tmatesoft.hg.util.Pair;
29
30 /**
31 * Connector-aware descriptor of remote repository, i.e. descriptor that uses
32 * {@link Connector Connectors} to connect to a remote repository.
33 *
34 * <p>Candidate to become public API, with createConnector() method, so that {@link HgRemoteRepository}
35 * may accept instances of that interfact directly
36 *
37 *
38 * @author Artem Tikhomirov
39 * @author TMate Software Ltd.
40 */
41 public class RemoteConnectorDescriptor implements RemoteDescriptor {
42
43 private Map<String, Pair<ClassLoader, String>> connFactory;
44 private final URI uri;
45
46 public RemoteConnectorDescriptor(Map<String,Pair<ClassLoader, String>> scheme2connectorMap, URI uriRemote) {
47 this(uriRemote);
48 connFactory = scheme2connectorMap;
49 }
50
51 protected RemoteConnectorDescriptor(URI uriRemote) {
52 uri = uriRemote;
53 }
54
55 public URI getURI() {
56 return uri;
57 }
58
59 public Authenticator getAuth() {
60 // TODO Auto-generated method stub
61 return null;
62 }
63
64 public Connector createConnector() throws HgBadArgumentException {
65 Pair<ClassLoader, String> connectorToBe = connFactory.get(uri.getScheme());
66 if (connectorToBe == null || connectorToBe.second() == null) {
67 throw new HgBadArgumentException(String.format("Can't instantiate connector for scheme '%s'", uri.getScheme()), null);
68 }
69 try {
70 Class<?> connClass = connectorToBe.first().loadClass(connectorToBe.second());
71 if (!Connector.class.isAssignableFrom(connClass)) {
72 throw new HgBadArgumentException(String.format("Connector %s for scheme '%s' is not a subclass of %s", connectorToBe.second(), uri.getScheme(), Connector.class.getName()), null);
73 }
74 final Object connector = connClass.newInstance();
75 return Connector.class.cast(connector);
76 } catch (ClassNotFoundException ex) {
77 throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex);
78 } catch (InstantiationException ex) {
79 throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex);
80 } catch (IllegalAccessException ex) {
81 throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex);
82 }
83 }
84
85 // I don't see a reason to expose provider of RemoteDescriptors yet
86 // although it might not be the best idea for session context to serve as provider intermediate
87 public static class Provider {
88 private final Map<String, Pair<ClassLoader, String>> knownConnectors = new HashMap<String, Pair<ClassLoader, String>>(5);
89
90 {
91 final ClassLoader cl = Provider.class.getClassLoader();
92 knownConnectors.put("http", new Pair<ClassLoader, String>(cl, HttpConnector.class.getName()));
93 knownConnectors.put("https", new Pair<ClassLoader, String>(cl, HttpConnector.class.getName()));
94 // FIXME replace SshConnector.class with fqn string to avoid dependency from the trilead library in runtime
95 knownConnectors.put("ssh", new Pair<ClassLoader, String>(cl, SshConnector.class.getName()));
96 }
97
98 public RemoteDescriptor get(SessionContext ctx, URI uri) {
99 if (knownConnectors.containsKey(uri.getScheme())) {
100 return new RemoteConnectorDescriptor(knownConnectors, uri);
101 }
102 return null;
103 }
104 }
105 }