1 /* 2 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> 3 * Copyright (C) 2008, 2022 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 class DefaultFactory { 40 41 private static volatile SshSessionFactory INSTANCE = loadSshSessionFactory(); 42 43 private static SshSessionFactory loadSshSessionFactory() { 44 ServiceLoader<SshSessionFactory> loader = ServiceLoader 45 .load(SshSessionFactory.class); 46 Iterator<SshSessionFactory> iter = loader.iterator(); 47 if (iter.hasNext()) { 48 return iter.next(); 49 } 50 return null; 51 } 52 53 private DefaultFactory() { 54 // No instantiation 55 } 56 57 public static SshSessionFactory getInstance() { 58 return INSTANCE; 59 } 60 61 public static void setInstance(SshSessionFactory newFactory) { 62 if (newFactory != null) { 63 INSTANCE = newFactory; 64 } else { 65 INSTANCE = loadSshSessionFactory(); 66 } 67 } 68 } 69 70 /** 71 * Gets the currently configured JVM-wide factory. 72 * <p> 73 * By default the factory will read from the user's {@code $HOME/.ssh} and 74 * assume OpenSSH compatibility. 75 * </p> 76 * 77 * @return factory the current factory for this JVM. 78 */ 79 public static SshSessionFactory getInstance() { 80 return DefaultFactory.getInstance(); 81 } 82 83 /** 84 * Changes the JVM-wide factory to a different implementation. 85 * 86 * @param newFactory 87 * factory for future sessions to be created through; if 88 * {@code null} the default factory will be restored. 89 */ 90 public static void setInstance(SshSessionFactory newFactory) { 91 DefaultFactory.setInstance(newFactory); 92 } 93 94 /** 95 * Retrieves the local user name as defined by the system property 96 * "user.name". 97 * 98 * @return the user name 99 * @since 5.2 100 */ 101 public static String getLocalUserName() { 102 return AccessController 103 .doPrivileged((PrivilegedAction<String>) () -> SystemReader 104 .getInstance().getProperty(Constants.OS_USER_NAME_KEY)); 105 } 106 107 /** 108 * Opens (or reuses) a session to a host. The returned session is connected 109 * and authenticated and is ready for further use. 110 * 111 * @param uri 112 * URI of the remote host to connect to 113 * @param credentialsProvider 114 * provider to support authentication, may be {@code null} if no 115 * user input for authentication is needed 116 * @param fs 117 * the file system abstraction to use for certain file 118 * operations, such as reading configuration files 119 * @param tms 120 * connection timeout for creating the session, in milliseconds 121 * @return a connected and authenticated session for communicating with the 122 * remote host given by the {@code uri} 123 * @throws org.eclipse.jgit.errors.TransportException 124 * if the session could not be created 125 */ 126 public abstract RemoteSession getSession(URIish uri, 127 CredentialsProvider credentialsProvider, FS fs, int tms) 128 throws TransportException; 129 130 /** 131 * The name of the type of session factory. 132 * 133 * @return the name of the type of session factory. 134 * 135 * @since 5.8 136 */ 137 public abstract String getType(); 138 139 /** 140 * Closes (or recycles) a session to a host. 141 * 142 * @param session 143 * a session previously obtained from this factory's 144 * {@link #getSession(URIish, CredentialsProvider, FS, int)} 145 * method. 146 */ 147 public void releaseSession(RemoteSession session) { 148 session.disconnect(); 149 } 150 }