1 /* 2 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> 3 * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.org> and others 4 * 5 * This program and the accompanying materials are made available under the 6 * terms of the Eclipse Distribution License v. 1.0 which is available at 7 * https://www.eclipse.org/org/documents/edl-v10.php. 8 * 9 * SPDX-License-Identifier: BSD-3-Clause 10 */ 11 12 package org.eclipse.jgit.transport; 13 14 import java.security.AccessController; 15 import java.security.PrivilegedAction; 16 import java.util.Iterator; 17 import java.util.ServiceLoader; 18 19 import org.eclipse.jgit.errors.TransportException; 20 import org.eclipse.jgit.lib.Constants; 21 import org.eclipse.jgit.util.FS; 22 import org.eclipse.jgit.util.SystemReader; 23 24 /** 25 * Creates and destroys SSH connections to a remote system. 26 * <p> 27 * Different implementations of the session factory may be used to control 28 * communicating with the end-user as well as reading their personal SSH 29 * configuration settings, such as known hosts and private keys. 30 * </p> 31 * <p> 32 * A {@link RemoteSession} must be returned to the factory that created it. 33 * Callers are encouraged to retain the SshSessionFactory for the duration of 34 * the period they are using the session. 35 * </p> 36 */ 37 public abstract class SshSessionFactory { 38 39 private static volatile SshSessionFactory INSTANCE = loadSshSessionFactory(); 40 41 private static SshSessionFactory loadSshSessionFactory() { 42 ServiceLoader<SshSessionFactory> loader = ServiceLoader.load(SshSessionFactory.class); 43 Iterator<SshSessionFactory> iter = loader.iterator(); 44 if(iter.hasNext()) { 45 return iter.next(); 46 } 47 return null; 48 } 49 50 /** 51 * Gets the currently configured JVM-wide factory. 52 * <p> 53 * By default the factory will read from the user's {@code $HOME/.ssh} and 54 * assume OpenSSH compatibility. 55 * </p> 56 * 57 * @return factory the current factory for this JVM. 58 */ 59 public static SshSessionFactory getInstance() { 60 return INSTANCE; 61 } 62 63 /** 64 * Changes the JVM-wide factory to a different implementation. 65 * 66 * @param newFactory 67 * factory for future sessions to be created through; if 68 * {@code null} the default factory will be restored. 69 */ 70 public static void setInstance(SshSessionFactory newFactory) { 71 if (newFactory != null) { 72 INSTANCE = newFactory; 73 } else { 74 INSTANCE = loadSshSessionFactory(); 75 } 76 } 77 78 /** 79 * Retrieves the local user name as defined by the system property 80 * "user.name". 81 * 82 * @return the user name 83 * @since 5.2 84 */ 85 public static String getLocalUserName() { 86 return AccessController 87 .doPrivileged((PrivilegedAction<String>) () -> SystemReader 88 .getInstance().getProperty(Constants.OS_USER_NAME_KEY)); 89 } 90 91 /** 92 * Opens (or reuses) a session to a host. The returned session is connected 93 * and authenticated and is ready for further use. 94 * 95 * @param uri 96 * URI of the remote host to connect to 97 * @param credentialsProvider 98 * provider to support authentication, may be {@code null} if no 99 * user input for authentication is needed 100 * @param fs 101 * the file system abstraction to use for certain file 102 * operations, such as reading configuration files 103 * @param tms 104 * connection timeout for creating the session, in milliseconds 105 * @return a connected and authenticated session for communicating with the 106 * remote host given by the {@code uri} 107 * @throws org.eclipse.jgit.errors.TransportException 108 * if the session could not be created 109 */ 110 public abstract RemoteSession getSession(URIish uri, 111 CredentialsProvider credentialsProvider, FS fs, int tms) 112 throws TransportException; 113 114 /** 115 * The name of the type of session factory. 116 * 117 * @return the name of the type of session factory. 118 * 119 * @since 5.8 120 */ 121 public abstract String getType(); 122 123 /** 124 * Closes (or recycles) a session to a host. 125 * 126 * @param session 127 * a session previously obtained from this factory's 128 * {@link #getSession(URIish, CredentialsProvider, FS, int)} 129 * method. 130 */ 131 public void releaseSession(RemoteSession session) { 132 session.disconnect(); 133 } 134 }