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 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 }