Browse Source
The new TransportProtocol type describes what a particular Transport implementation wants in order to support a connection. 3rd parties can now plug into the Transport.open() logic by implementing their own TransportProtocol and Transport classes, and registering with Transport.register(). GUI applications can help the user configure a connection by looking at the supported fields of a particular TransportProtocol type, which makes the GUI more dynamic and may better support new Transports. Change-Id: Iafd8e3a6285261412aac6cba8e2c333f8b7b76a5 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>stable-0.12
Shawn O. Pearce
14 years ago
15 changed files with 703 additions and 146 deletions
@ -0,0 +1,221 @@
|
||||
/* |
||||
* Copyright (C) 2011, Google Inc. |
||||
* and other copyright owners as documented in the project's IP log. |
||||
* |
||||
* This program and the accompanying materials are made available |
||||
* under the terms of the Eclipse Distribution License v1.0 which |
||||
* accompanies this distribution, is reproduced below, and is |
||||
* available at http://www.eclipse.org/org/documents/edl-v10.php
|
||||
* |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or |
||||
* without modification, are permitted provided that the following |
||||
* conditions are met: |
||||
* |
||||
* - Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* |
||||
* - Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following |
||||
* disclaimer in the documentation and/or other materials provided |
||||
* with the distribution. |
||||
* |
||||
* - Neither the name of the Eclipse Foundation, Inc. nor the |
||||
* names of its contributors may be used to endorse or promote |
||||
* products derived from this software without specific prior |
||||
* written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
*/ |
||||
|
||||
package org.eclipse.jgit.transport; |
||||
|
||||
import java.util.Collections; |
||||
import java.util.EnumSet; |
||||
import java.util.Set; |
||||
|
||||
import org.eclipse.jgit.errors.NotSupportedException; |
||||
import org.eclipse.jgit.errors.TransportException; |
||||
import org.eclipse.jgit.lib.Repository; |
||||
|
||||
/** |
||||
* Describes a way to connect to another Git repository. |
||||
* <p> |
||||
* Implementations of this class are typically immutable singletons held by |
||||
* static class members, for example: |
||||
* |
||||
* <pre> |
||||
* class MyTransport extends Transport { |
||||
* static final TransportProtocol PROTO = new TransportProtocol() { |
||||
* public String getName() { |
||||
* return "My Protocol"; |
||||
* } |
||||
* }; |
||||
* } |
||||
* </pre> |
||||
* |
||||
* Applications may register additional protocols for use by JGit by calling |
||||
* {@link Transport#register(TransportProtocol)}. Because that API holds onto |
||||
* the protocol object by a WeakReference, applications must ensure their own |
||||
* ClassLoader retains the TransportProtocol for the life of the application. |
||||
* Using a static singleton pattern as above will ensure the protocol is valid |
||||
* so long as the ClassLoader that defines it remains valid. |
||||
*/ |
||||
public abstract class TransportProtocol { |
||||
/** Fields within a {@link URIish} that a transport uses. */ |
||||
public static enum URIishField { |
||||
/** the user field */ |
||||
USER, |
||||
/** the pass (aka password) field */ |
||||
PASS, |
||||
/** the host field */ |
||||
HOST, |
||||
/** the port field */ |
||||
PORT, |
||||
/** the path field */ |
||||
PATH, |
||||
} |
||||
|
||||
/** @return text name of the protocol suitable for display to a user. */ |
||||
public abstract String getName(); |
||||
|
||||
/** @return immutable set of schemes supported by this protocol. */ |
||||
public Set<String> getSchemes() { |
||||
return Collections.emptySet(); |
||||
} |
||||
|
||||
/** @return immutable set of URIishFields that must be filled in. */ |
||||
public Set<URIishField> getRequiredFields() { |
||||
return Collections.unmodifiableSet(EnumSet.of(URIishField.PATH)); |
||||
} |
||||
|
||||
/** @return immutable set of URIishFields that may be filled in. */ |
||||
public Set<URIishField> getOptionalFields() { |
||||
return Collections.emptySet(); |
||||
} |
||||
|
||||
/** @return if a port is supported, the default port, else -1. */ |
||||
public int getDefaultPort() { |
||||
return -1; |
||||
} |
||||
|
||||
/** |
||||
* Determine if this protocol can handle a particular URI. |
||||
* <p> |
||||
* Implementations should try to avoid looking at the local filesystem, but |
||||
* may look at implementation specific configuration options in the remote |
||||
* block of {@code local.getConfig()} using {@code remoteName} if the name |
||||
* is non-null. |
||||
* <p> |
||||
* The default implementation of this method matches the scheme against |
||||
* {@link #getSchemes()}, required fields against |
||||
* {@link #getRequiredFields()}, and optional fields against |
||||
* {@link #getOptionalFields()}, returning true only if all of the fields |
||||
* match the specification. |
||||
* |
||||
* @param local |
||||
* the local repository that will communicate with the other Git |
||||
* repository. |
||||
* @param uri |
||||
* address of the Git repository; never null. |
||||
* @param remoteName |
||||
* name of the remote, if the remote as configured in |
||||
* {@code local}; otherwise null. |
||||
* @return true if this protocol can handle this URI; false otherwise. |
||||
*/ |
||||
public boolean canHandle(Repository local, URIish uri, String remoteName) { |
||||
if (!getSchemes().isEmpty() && !getSchemes().contains(uri.getScheme())) |
||||
return false; |
||||
|
||||
for (URIishField field : getRequiredFields()) { |
||||
switch (field) { |
||||
case USER: |
||||
if (uri.getUser() == null || uri.getUser().length() == 0) |
||||
return false; |
||||
break; |
||||
|
||||
case PASS: |
||||
if (uri.getPass() == null || uri.getPass().length() == 0) |
||||
return false; |
||||
break; |
||||
|
||||
case HOST: |
||||
if (uri.getHost() == null || uri.getHost().length() == 0) |
||||
return false; |
||||
break; |
||||
|
||||
case PORT: |
||||
if (uri.getPort() <= 0) |
||||
return false; |
||||
break; |
||||
|
||||
case PATH: |
||||
if (uri.getPath() == null || uri.getPath().length() == 0) |
||||
return false; |
||||
break; |
||||
|
||||
default: |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
Set<URIishField> canHave = EnumSet.copyOf(getRequiredFields()); |
||||
canHave.addAll(getOptionalFields()); |
||||
|
||||
if (uri.getUser() != null && !canHave.contains(URIishField.USER)) |
||||
return false; |
||||
if (uri.getPass() != null && !canHave.contains(URIishField.PASS)) |
||||
return false; |
||||
if (uri.getHost() != null && !canHave.contains(URIishField.HOST)) |
||||
return false; |
||||
if (uri.getPort() > 0 && !canHave.contains(URIishField.PORT)) |
||||
return false; |
||||
if (uri.getPath() != null && !canHave.contains(URIishField.PATH)) |
||||
return false; |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* Open a Transport instance to the other repository. |
||||
* <p> |
||||
* Implementations should avoid making remote connections until an operation |
||||
* on the returned Transport is invoked, however they may fail fast here if |
||||
* they know a connection is impossible, such as when using the local |
||||
* filesystem and the target path does not exist. |
||||
* <p> |
||||
* Implementations may access implementation-specific configuration options |
||||
* within {@code local.getConfig()} using the remote block named by the |
||||
* {@code remoteName}, if the name is non-null. |
||||
* |
||||
* @param local |
||||
* the local repository that will communicate with the other Git |
||||
* repository. |
||||
* @param uri |
||||
* address of the Git repository. |
||||
* @param remoteName |
||||
* name of the remote, if the remote as configured in |
||||
* {@code local}; otherwise null. |
||||
* @return the transport. |
||||
* @throws NotSupportedException |
||||
* this protocol does not support the URI. |
||||
* @throws TransportException |
||||
* the transport cannot open this URI. |
||||
*/ |
||||
public abstract Transport open(Repository local, URIish uri, |
||||
String remoteName) |
||||
throws NotSupportedException, TransportException; |
||||
} |
Loading…
Reference in new issue