tikhomirov@698: /* tikhomirov@698: * Copyright (c) 2013 TMate Software Ltd tikhomirov@698: * tikhomirov@698: * This program is free software; you can redistribute it and/or modify tikhomirov@698: * it under the terms of the GNU General Public License as published by tikhomirov@698: * the Free Software Foundation; version 2 of the License. tikhomirov@698: * tikhomirov@698: * This program is distributed in the hope that it will be useful, tikhomirov@698: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@698: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@698: * GNU General Public License for more details. tikhomirov@698: * tikhomirov@698: * For information on how to redistribute this software under tikhomirov@698: * the terms of a license other than GNU General Public License tikhomirov@698: * contact TMate Software at support@hg4j.com tikhomirov@698: */ tikhomirov@698: package org.tmatesoft.hg.internal.remote; tikhomirov@698: tikhomirov@698: import java.net.URI; tikhomirov@698: import java.util.HashMap; tikhomirov@698: import java.util.Map; tikhomirov@698: tikhomirov@698: import org.tmatesoft.hg.core.HgBadArgumentException; tikhomirov@698: import org.tmatesoft.hg.core.SessionContext; tikhomirov@698: import org.tmatesoft.hg.repo.HgRemoteRepository; tikhomirov@698: import org.tmatesoft.hg.util.Pair; tikhomirov@698: tikhomirov@698: /** tikhomirov@698: * Connector-aware descriptor of remote repository, i.e. descriptor that uses tikhomirov@698: * {@link Connector Connectors} to connect to a remote repository. tikhomirov@698: * tikhomirov@698: *

Candidate to become public API, with createConnector() method, so that {@link HgRemoteRepository} tikhomirov@698: * may accept instances of that interfact directly tikhomirov@698: * tikhomirov@698: * tikhomirov@698: * @author Artem Tikhomirov tikhomirov@698: * @author TMate Software Ltd. tikhomirov@698: */ tikhomirov@699: public class RemoteConnectorDescriptor implements HgRemoteRepository.RemoteDescriptor { tikhomirov@698: tikhomirov@698: private Map> connFactory; tikhomirov@698: private final URI uri; tikhomirov@698: tikhomirov@698: public RemoteConnectorDescriptor(Map> scheme2connectorMap, URI uriRemote) { tikhomirov@698: this(uriRemote); tikhomirov@698: connFactory = scheme2connectorMap; tikhomirov@698: } tikhomirov@698: tikhomirov@698: protected RemoteConnectorDescriptor(URI uriRemote) { tikhomirov@698: uri = uriRemote; tikhomirov@698: } tikhomirov@698: tikhomirov@698: public URI getURI() { tikhomirov@698: return uri; tikhomirov@698: } tikhomirov@698: tikhomirov@698: public Connector createConnector() throws HgBadArgumentException { tikhomirov@698: Pair connectorToBe = connFactory.get(uri.getScheme()); tikhomirov@698: if (connectorToBe == null || connectorToBe.second() == null) { tikhomirov@698: throw new HgBadArgumentException(String.format("Can't instantiate connector for scheme '%s'", uri.getScheme()), null); tikhomirov@698: } tikhomirov@698: try { tikhomirov@698: Class connClass = connectorToBe.first().loadClass(connectorToBe.second()); tikhomirov@698: if (!Connector.class.isAssignableFrom(connClass)) { tikhomirov@698: throw new HgBadArgumentException(String.format("Connector %s for scheme '%s' is not a subclass of %s", connectorToBe.second(), uri.getScheme(), Connector.class.getName()), null); tikhomirov@698: } tikhomirov@698: final Object connector = connClass.newInstance(); tikhomirov@698: return Connector.class.cast(connector); tikhomirov@698: } catch (ClassNotFoundException ex) { tikhomirov@698: throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex); tikhomirov@698: } catch (InstantiationException ex) { tikhomirov@698: throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex); tikhomirov@698: } catch (IllegalAccessException ex) { tikhomirov@698: throw new HgBadArgumentException(String.format("Can't instantiate connector %s for scheme '%s'", connectorToBe.second(), uri.getScheme()), ex); tikhomirov@698: } tikhomirov@698: } tikhomirov@698: tikhomirov@698: // I don't see a reason to expose provider of RemoteDescriptors yet tikhomirov@698: // although it might not be the best idea for session context to serve as provider intermediate tikhomirov@698: public static class Provider { tikhomirov@698: private final Map> knownConnectors = new HashMap>(5); tikhomirov@698: tikhomirov@698: { tikhomirov@698: final ClassLoader cl = Provider.class.getClassLoader(); tikhomirov@698: knownConnectors.put("http", new Pair(cl, HttpConnector.class.getName())); tikhomirov@698: knownConnectors.put("https", new Pair(cl, HttpConnector.class.getName())); tikhomirov@702: knownConnectors.put("ssh", new Pair(cl, "org.tmatesoft.hg.internal.remote.SshConnector")); tikhomirov@698: } tikhomirov@698: tikhomirov@699: public HgRemoteRepository.RemoteDescriptor get(SessionContext ctx, URI uri) { tikhomirov@698: if (knownConnectors.containsKey(uri.getScheme())) { tikhomirov@698: return new RemoteConnectorDescriptor(knownConnectors, uri); tikhomirov@698: } tikhomirov@698: return null; tikhomirov@698: } tikhomirov@698: } tikhomirov@698: }