update to OpenJDK 21, update to Grdle 8.4, add key parameter for loading private key by classloader
This commit is contained in:
parent
4eff2cd434
commit
2b879107d7
35 changed files with 139 additions and 174 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -15,6 +15,7 @@ logs
|
|||
*~
|
||||
.secret
|
||||
build
|
||||
**/*.key
|
||||
**/*.crt
|
||||
**/*.pkcs8
|
||||
**/*.gz
|
||||
|
|
11
build.gradle
11
build.gradle
|
@ -4,9 +4,10 @@ plugins {
|
|||
id "pmd"
|
||||
id 'maven-publish'
|
||||
id 'signing'
|
||||
id "io.github.gradle-nexus.publish-plugin" version "1.3.0"
|
||||
id "com.github.spotbugs" version "5.0.14"
|
||||
id "org.cyclonedx.bom" version "1.7.2"
|
||||
id "io.github.gradle-nexus.publish-plugin" version "2.0.0-rc-1"
|
||||
id "com.github.spotbugs" version "6.0.0-beta.3"
|
||||
id "org.cyclonedx.bom" version "1.7.4"
|
||||
id "org.xbib.gradle.plugin.asciidoctor" version "3.0.0"
|
||||
}
|
||||
|
||||
wrapper {
|
||||
|
@ -30,14 +31,14 @@ ext {
|
|||
}
|
||||
|
||||
subprojects {
|
||||
apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||
//apply from: rootProject.file('gradle/ide/idea.gradle')
|
||||
apply from: rootProject.file('gradle/repositories/maven.gradle')
|
||||
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||
apply from: rootProject.file('gradle/publish/maven.gradle')
|
||||
apply from: rootProject.file('gradle/quality/checkstyle.gradle')
|
||||
apply from: rootProject.file('gradle/quality/pmd.gradle')
|
||||
apply from: rootProject.file('gradle/quality/spotbugs.gradle')
|
||||
//apply from: rootProject.file('gradle/quality/spotbugs.gradle')
|
||||
}
|
||||
apply from: rootProject.file('gradle/publish/sonatype.gradle')
|
||||
apply from: rootProject.file('gradle/publish/forgejo.gradle')
|
||||
|
|
|
@ -49,11 +49,11 @@ import static org.junit.jupiter.api.Assertions.assertNotSame;
|
|||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Matchers.anyBoolean;
|
||||
import static org.mockito.Matchers.anyCollectionOf;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
@ -330,7 +330,7 @@ public class FTPFileSystemTest extends AbstractFTPFileSystemTest {
|
|||
try (OutputStream input = getFileSystem().newOutputStream(createPath("/foo/bar"), options)) {
|
||||
// don't do anything with the stream, there's a separate test for that
|
||||
} finally {
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/foo/bar"), eq(553), anyString(), anyCollectionOf(OpenOption.class));
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/foo/bar"), eq(553), anyString(), anyList());
|
||||
assertSame(foo, getFileSystemEntry("/foo"));
|
||||
assertSame(bar, getFileSystemEntry("/foo/bar"));
|
||||
}
|
||||
|
@ -347,7 +347,7 @@ public class FTPFileSystemTest extends AbstractFTPFileSystemTest {
|
|||
try (OutputStream input = getFileSystem().newOutputStream(createPath("/foo/bar"), options)) {
|
||||
// don't do anything with the stream, there's a separate test for that
|
||||
} finally {
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/foo/bar"), eq(553), anyString(), anyCollectionOf(OpenOption.class));
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/foo/bar"), eq(553), anyString(), anyList());
|
||||
assertSame(foo, getFileSystemEntry("/foo"));
|
||||
assertSame(bar, getFileSystemEntry("/foo/bar"));
|
||||
}
|
||||
|
@ -427,8 +427,7 @@ public class FTPFileSystemTest extends AbstractFTPFileSystemTest {
|
|||
try (OutputStream input = getFileSystem().newOutputStream(createPath("/foo"), options)) {
|
||||
// don't do anything with the stream, there's a separate test for that
|
||||
} finally {
|
||||
verify(getExceptionFactory(), never()).createNewOutputStreamException(anyString(), anyInt(), anyString(),
|
||||
anyCollectionOf(OpenOption.class));
|
||||
verify(getExceptionFactory(), never()).createNewOutputStreamException(anyString(), anyInt(), anyString(), anyList());
|
||||
assertSame(foo, getFileSystemEntry("/foo"));
|
||||
assertEquals(0, getChildCount("/foo"));
|
||||
}
|
||||
|
@ -443,8 +442,7 @@ public class FTPFileSystemTest extends AbstractFTPFileSystemTest {
|
|||
try (OutputStream input = getFileSystem().newOutputStream(createPath("/foo"), options)) {
|
||||
// don't do anything with the stream, there's a separate test for that
|
||||
} finally {
|
||||
verify(getExceptionFactory(), never()).createNewOutputStreamException(anyString(), anyInt(), anyString(),
|
||||
anyCollectionOf(OpenOption.class));
|
||||
verify(getExceptionFactory(), never()).createNewOutputStreamException(anyString(), anyInt(), anyString(), anyList());
|
||||
assertSame(foo, getFileSystemEntry("/foo"));
|
||||
assertEquals(0, getChildCount("/foo"));
|
||||
}
|
||||
|
@ -693,7 +691,7 @@ public class FTPFileSystemTest extends AbstractFTPFileSystemTest {
|
|||
try {
|
||||
getFileSystem().copy(createPath("/foo/bar"), createPath("/baz/bar"), options);
|
||||
} finally {
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/baz/bar"), eq(553), anyString(), anyCollectionOf(OpenOption.class));
|
||||
verify(getExceptionFactory()).createNewOutputStreamException(eq("/baz/bar"), eq(553), anyString(), anyList());
|
||||
assertSame(foo, getFileSystemEntry("/foo"));
|
||||
assertSame(bar, getFileSystemEntry("/foo/bar"));
|
||||
assertNull(getFileSystemEntry("/baz"));
|
||||
|
|
|
@ -2755,7 +2755,7 @@ public class FTPClient extends FTP implements Configurable {
|
|||
* happen when parserKey is neither
|
||||
* the fully qualified class name of a class
|
||||
* implementing the interface
|
||||
* {@link }FTPFileEntryParser}
|
||||
* {@link FTPFileEntryParser}
|
||||
* nor a string containing one of the recognized keys
|
||||
* mapping to such a parser or if class loader
|
||||
* security issues prevent its being loaded.
|
||||
|
|
|
@ -7,7 +7,7 @@ module org.xbib.files.sftp.fs {
|
|||
exports org.apache.sshd.fs;
|
||||
exports org.apache.sshd.fs.spi;
|
||||
requires org.xbib.files;
|
||||
requires transitive org.xbib.files.sftp;
|
||||
requires org.xbib.files.sftp;
|
||||
provides FileSystemProvider with SftpFileSystemProvider;
|
||||
provides FileServiceProvider with SFTPFileServiceProvider;
|
||||
requires java.logging;
|
||||
|
|
|
@ -83,6 +83,7 @@ import org.apache.sshd.common.auth.BasicCredentialsImpl;
|
|||
import org.apache.sshd.common.auth.BasicCredentialsProvider;
|
||||
import org.apache.sshd.common.auth.MutableBasicCredentials;
|
||||
import org.apache.sshd.common.io.IoSession;
|
||||
import org.apache.sshd.common.keyprovider.ClassLoadableResourceKeyPairProvider;
|
||||
import org.apache.sshd.common.keyprovider.KeyIdentityProvider;
|
||||
import org.apache.sshd.common.util.GenericUtils;
|
||||
import org.apache.sshd.common.util.NumberUtils;
|
||||
|
@ -197,12 +198,13 @@ public class SftpFileSystemProvider extends FileSystemProvider {
|
|||
if (port <= 0) {
|
||||
port = SshConstants.DEFAULT_PORT;
|
||||
}
|
||||
|
||||
Object o = env.get("username");
|
||||
String username = o instanceof String ? (String) o : o != null ? o.toString() : null;
|
||||
o = env.get("password");
|
||||
char[] password = o instanceof char[] ? (char[]) o : o instanceof String ? ((String)o).toCharArray() : null;
|
||||
|
||||
if (env.containsKey("key")) {
|
||||
clientInstance.setKeyIdentityProvider(new ClassLoadableResourceKeyPairProvider(env.get("key").toString()));
|
||||
}
|
||||
boolean disableServerKeys = "true".equals(env.get("disableServerKeys"));
|
||||
if (disableServerKeys) {
|
||||
clientInstance.setServerKeyVerifier(AcceptAllServerKeyVerifier.INSTANCE);
|
||||
|
@ -280,7 +282,7 @@ public class SftpFileSystemProvider extends FileSystemProvider {
|
|||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
} catch (IOException t) {
|
||||
} catch (Exception t) {
|
||||
e.addSuppressed(t);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,23 +4,11 @@ import org.junit.jupiter.api.Test;
|
|||
import org.xbib.files.FileService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Provider;
|
||||
import java.security.Security;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class FileServiceProviderTest {
|
||||
|
||||
static {
|
||||
// load bouncy castle provider (and other security providers)
|
||||
for (Provider p : ServiceLoader.load(Provider.class)) {
|
||||
if (Security.getProvider(p.getName()) == null) {
|
||||
Security.addProvider(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSFTP() throws IOException {
|
||||
Map<String, ?> env = Map.of("username", "joerg");
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package org.apache.sshd.fs.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.files.FileService;
|
||||
|
||||
public class SftpClientTest {
|
||||
|
||||
@Test
|
||||
public void testSFTP() throws IOException {
|
||||
String targetURLString = "sftp://fernleihe-test.hbz-nrw.de:22";
|
||||
String targetIdString = "malva";
|
||||
URI uri = URI.create(targetURLString);
|
||||
FileService fs = FileService.newInstance(targetURLString,
|
||||
Map.of("username", targetIdString,
|
||||
"key", uri.getHost() + "/" + targetIdString + ".key"));
|
||||
fs.list(".").forEach(p -> Logger.getAnonymousLogger().info(p.toString()));
|
||||
}
|
||||
}
|
|
@ -75,7 +75,6 @@ import org.apache.sshd.common.Factory;
|
|||
import org.apache.sshd.common.NamedResource;
|
||||
import org.apache.sshd.common.ServiceFactory;
|
||||
import org.apache.sshd.common.config.keys.FilePasswordProvider;
|
||||
import org.apache.sshd.common.config.keys.KeyUtils;
|
||||
import org.apache.sshd.common.config.keys.PublicKeyEntry;
|
||||
import org.apache.sshd.common.future.SshFutureListener;
|
||||
import org.apache.sshd.common.helpers.AbstractFactoryManager;
|
||||
|
@ -732,7 +731,6 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
|
|||
} else if (id instanceof KeyPair) {
|
||||
KeyPair kp = (KeyPair) id;
|
||||
session.addPublicKeyIdentity(kp);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import org.apache.sshd.common.util.GenericUtils;
|
|||
public interface PasswordIdentityProvider {
|
||||
|
||||
/**
|
||||
* An "empty" implementation of {@link PasswordIdentityProvider} that returns and empty group of passwords
|
||||
* An "empty" implementation of {@link PasswordIdentityProvider} that returns and empty group of passwords
|
||||
*/
|
||||
PasswordIdentityProvider EMPTY_PASSWORDS_PROVIDER = new PasswordIdentityProvider() {
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
package org.apache.sshd.client.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.SocketAddress;
|
||||
import java.security.KeyPair;
|
||||
|
||||
|
@ -82,12 +83,16 @@ public class SimpleSftpClientImpl implements SimpleSftpClient {
|
|||
SimpleClient client = getClient();
|
||||
ClientSession session = sessionProvider.apply(client);
|
||||
try {
|
||||
SftpClient sftp = createSftpClient(session);
|
||||
session = null; // disable auto-close at finally block
|
||||
return sftp;
|
||||
SftpClient sftpClient = createSftpClient(session);
|
||||
session = null;
|
||||
return sftpClient;
|
||||
} finally {
|
||||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
} catch (Exception e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ import org.apache.sshd.common.CoreModuleProperties;
|
|||
|
||||
/**
|
||||
* Provides a way to implement proxied connections where some metadata about the client is sent <U>before</U> the actual
|
||||
* SSH protocol is executed - e.g., the <A HREF=@http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt">PROXY
|
||||
* protocol</A>. The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the
|
||||
* SSH protocol is executed - e.g., the http://www.haproxy.org/download/1.6/doc/proxy-protocol.txt PROXY
|
||||
* protocol. The implementor should use the {@code IoSession#write(Buffer)} method to send any packets with the
|
||||
* meta-data.
|
||||
*
|
||||
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
|
||||
|
|
|
@ -18,13 +18,8 @@
|
|||
*/
|
||||
package org.apache.sshd.client.session;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.PublicKey;
|
||||
import java.time.Duration;
|
||||
|
|
|
@ -125,8 +125,8 @@ public abstract class AbstractSimpleClientSessionCreator extends AbstractSimpleC
|
|||
if (session != null) {
|
||||
try {
|
||||
session.close();
|
||||
} catch (IOException e) {
|
||||
err = GenericUtils.accumulateException(err, e);
|
||||
} catch (Exception e) {
|
||||
err = GenericUtils.accumulateException(err, new IOException(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.apache.sshd.common.future.SshFutureListener;
|
|||
*
|
||||
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
|
||||
*/
|
||||
public interface Closeable extends Channel {
|
||||
public interface Closeable extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* Close this resource asynchronously and return a future. Resources support two closing modes: a graceful mode
|
||||
|
@ -76,13 +76,12 @@ public interface Closeable extends Channel {
|
|||
*/
|
||||
boolean isClosing();
|
||||
|
||||
@Override
|
||||
default boolean isOpen() {
|
||||
return !(isClosed() || isClosing());
|
||||
}
|
||||
|
||||
@Override
|
||||
default void close() throws IOException {
|
||||
default void close() throws Exception {
|
||||
Closeable.close(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,6 @@ public final class CoreModuleProperties {
|
|||
public static final Property<String> PROXY_AUTH_CHANNEL_TYPE
|
||||
= Property.string("ssh-agent-factory-proxy-auth-channel-type", "auth-agent-req@openssh.com");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.agent.local.ProxyAgentFactory#getChannelForwardingFactories}
|
||||
*/
|
||||
public static final Property<Boolean> PREFER_UNIX_AGENT
|
||||
= Property.bool("ssh-prefer-unix-agent", OsUtils.isUNIX());
|
||||
|
||||
|
@ -147,8 +144,6 @@ public final class CoreModuleProperties {
|
|||
|
||||
/**
|
||||
* Whether to ignore invalid identities files when pre-initializing the client session
|
||||
*
|
||||
* @see ClientIdentityLoader#isValidLocation(NamedResource)
|
||||
*/
|
||||
public static final Property<Boolean> IGNORE_INVALID_IDENTITIES
|
||||
= Property.bool("ignore-invalid-identities", true);
|
||||
|
@ -579,105 +574,84 @@ public final class CoreModuleProperties {
|
|||
public static final Property<String> MODULI_URL
|
||||
= Property.string("moduli-url");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}.
|
||||
*/
|
||||
public static final Property<String> KB_SERVER_INTERACTIVE_NAME
|
||||
= Property.string("kb-server-interactive-name", "Password authentication");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}.
|
||||
*/
|
||||
public static final Property<String> KB_SERVER_INTERACTIVE_INSTRUCTION
|
||||
= Property.string("kb-server-interactive-instruction", "");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}.
|
||||
*/
|
||||
public static final Property<String> KB_SERVER_INTERACTIVE_LANG
|
||||
= Property.string("kb-server-interactive-language", "en-US");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}.
|
||||
*/
|
||||
public static final Property<String> KB_SERVER_INTERACTIVE_PROMPT
|
||||
= Property.string("kb-server-interactive-prompt", "Password: ");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.auth.keyboard.DefaultKeyboardInteractiveAuthenticator}.
|
||||
*/
|
||||
public static final Property<Boolean> KB_SERVER_INTERACTIVE_ECHO_PROMPT
|
||||
= Property.bool("kb-server-interactive-echo-prompt", false);
|
||||
|
||||
/**
|
||||
* Maximum amount of extended (a.k.a. STDERR) data allowed to be accumulated until a {@link ChannelDataReceiver} for
|
||||
* Maximum amount of extended (a.k.a. STDERR) data allowed to be accumulated until a ChannelDataReceiver for
|
||||
* the data is registered
|
||||
*/
|
||||
public static final Property<Integer> MAX_EXTDATA_BUFSIZE
|
||||
= Property.integer("channel-session-max-extdata-bufsize", 0);
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.kex.DHGEXServer}.
|
||||
*/
|
||||
public static final Property<Integer> PROP_DHGEX_SERVER_MIN_KEY
|
||||
= Property.integer("dhgex-server-min");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.server.kex.DHGEXServer}.
|
||||
*/
|
||||
public static final Property<Integer> PROP_DHGEX_SERVER_MAX_KEY
|
||||
= Property.integer("dhgex-server-max");
|
||||
/**
|
||||
* Value used by the {@link org.apache.sshd.server.shell.InvertedShellWrapper} to control the "busy-wait"
|
||||
* Value used to control the "busy-wait"
|
||||
* sleep time (millis) on the pumping loop if nothing was pumped - must be <U>positive</U>.
|
||||
*/
|
||||
public static final Property<Duration> PUMP_SLEEP_TIME
|
||||
= Property.duration("inverted-shell-wrapper-pump-sleep", Duration.ofMillis(1));
|
||||
|
||||
/**
|
||||
* Value used by the {@link org.apache.sshd.server.shell.InvertedShellWrapper} to control copy buffer size.
|
||||
* Value used to control copy buffer size.
|
||||
*/
|
||||
public static final Property<Integer> BUFFER_SIZE
|
||||
= Property.integer("inverted-shell-wrapper-buffer-size", IoUtils.DEFAULT_COPY_SIZE);
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the channel open
|
||||
* Configuration value to control the channel open
|
||||
* timeout.
|
||||
*/
|
||||
public static final Property<Duration> X11_OPEN_TIMEOUT
|
||||
= Property.duration("x11-fwd-open-timeout", Duration.ofSeconds(30L));
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control from which X11
|
||||
* Configuration value to control from which X11
|
||||
* display number to start looking for a free value.
|
||||
*/
|
||||
public static final Property<Integer> X11_DISPLAY_OFFSET
|
||||
= Property.integer("x11-fwd-display-offset", 10);
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control up to which (but not
|
||||
* Configuration value to control up to which (but not
|
||||
* including) X11 display number to look or a free value.
|
||||
*/
|
||||
public static final Property<Integer> X11_MAX_DISPLAYS
|
||||
= Property.integer("x11-fwd-max-display", 1000);
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the base port number
|
||||
* Configuration value to control the base port number
|
||||
* for the X11 display number socket binding.
|
||||
*/
|
||||
public static final Property<Integer> X11_BASE_PORT
|
||||
= Property.integer("x11-fwd-base-port", 6000);
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.x11.X11ForwardSupport} to control the host used to bind
|
||||
* Configuration value to control the host used to bind
|
||||
* to for the X11 display when looking for a free port.
|
||||
*/
|
||||
public static final Property<String> X11_BIND_HOST
|
||||
= Property.string("x11-fwd-bind-host", SshdSocketAddress.LOCALHOST_IPV4);
|
||||
|
||||
/**
|
||||
* Configuration value for the {@link org.apache.sshd.server.forward.TcpipServerChannel} to control the higher
|
||||
* theshold for the data to be buffered waiting to be sent. If the buffered data size reaches this value, the
|
||||
* Configuration value to control the higher
|
||||
* threshold for the data to be buffered waiting to be sent. If the buffered data size reaches this value, the
|
||||
* session will pause reading until the data length goes below the
|
||||
* {@link #TCPIP_SERVER_CHANNEL_BUFFER_SIZE_THRESHOLD_LOW} threshold.
|
||||
*/
|
||||
|
|
|
@ -23,9 +23,6 @@ import java.nio.charset.StandardCharsets;
|
|||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.apache.sshd.common.Property;
|
||||
import org.apache.sshd.common.PropertyResolver;
|
||||
import org.apache.sshd.common.SshConstants;
|
||||
import org.apache.sshd.common.util.ValidateUtils;
|
||||
import org.apache.sshd.common.util.buffer.Buffer;
|
||||
import org.apache.sshd.common.util.io.IoUtils;
|
||||
|
@ -41,8 +38,6 @@ public final class SftpModuleProperties {
|
|||
* Used to indicate the {@link Charset} (or its name) for decoding referenced files/folders names - extracted from
|
||||
* the client session when 1st initialized.
|
||||
*
|
||||
* @see SftpClient#getNameDecodingCharset()
|
||||
* @see SftpClient#setNameDecodingCharset(Charset)
|
||||
*/
|
||||
public static final Property<Charset> NAME_DECODING_CHARSET
|
||||
= Property.charset("sftp-name-decoding-charset", StandardCharsets.UTF_8);
|
||||
|
@ -54,45 +49,26 @@ public final class SftpModuleProperties {
|
|||
public static final Property<Duration> SFTP_CHANNEL_OPEN_TIMEOUT
|
||||
= Property.duration("sftp-channel-open-timeout", Duration.ofSeconds(15L));
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystem}.
|
||||
*/
|
||||
public static final Property<Integer> POOL_SIZE
|
||||
= Property.integer("sftp-fs-pool-size", 8);
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystemProvider}.
|
||||
*/
|
||||
public static final Property<Integer> READ_BUFFER_SIZE
|
||||
= Property.integer("sftp-fs-read-buffer-size");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystemProvider}.
|
||||
*/
|
||||
public static final Property<Integer> WRITE_BUFFER_SIZE
|
||||
= Property.integer("sftp-fs-write-buffer-size");
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystemProvider}.
|
||||
*/
|
||||
public static final Property<Duration> CONNECT_TIME
|
||||
= Property.duration("sftp-fs-connect-time", Duration.ofSeconds(15L));
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystemProvider}.
|
||||
*/
|
||||
public static final Property<Duration> AUTH_TIME
|
||||
= Property.duration("sftp-fs-auth-time", Duration.ofSeconds(15L));
|
||||
|
||||
/**
|
||||
* See {@link org.apache.sshd.sftp.client.fs.SftpFileSystemProvider}.
|
||||
*/
|
||||
public static final Property<Charset> NAME_DECODER_CHARSET
|
||||
= Property.charset("sftp-fs-name-decoder-charset", StandardCharsets.UTF_8);
|
||||
|
||||
/**
|
||||
* Property used to avoid large buffers when
|
||||
* {@link org.apache.sshd.sftp.client.impl.AbstractSftpClient#write(SftpClient.Handle, long, byte[], int, int)} is
|
||||
* invoked with a large buffer size.
|
||||
*/
|
||||
public static final Property<Integer> WRITE_CHUNK_SIZE
|
||||
|
@ -122,25 +98,22 @@ public final class SftpModuleProperties {
|
|||
/**
|
||||
* Allows controlling reports of which client extensions are supported (and reported via "support" and
|
||||
* "support2" server extensions) as a comma-separate list of names. <B>Note:</B> requires overriding the
|
||||
* {@link AbstractSftpSubsystemHelper#executeExtendedCommand(Buffer, int, String)} command accordingly. If empty
|
||||
* command accordingly. If empty
|
||||
* string is set then no server extensions are reported
|
||||
*
|
||||
* @see AbstractSftpSubsystemHelper#DEFAULT_SUPPORTED_CLIENT_EXTENSIONS
|
||||
*/
|
||||
public static final Property<String> CLIENT_EXTENSIONS
|
||||
= Property.string("sftp-client-extensions");
|
||||
|
||||
/**
|
||||
* Comma-separated list of which {@code OpenSSH} extensions are reported and what version is reported for each -
|
||||
* format: {@code name=version}. If empty value set, then no such extensions are reported. Otherwise, the
|
||||
* {@link AbstractSftpSubsystemHelper#DEFAULT_OPEN_SSH_EXTENSIONS} are used
|
||||
* format: {@code name=version}. If empty value set, then no such extensions are reported.
|
||||
*/
|
||||
public static final Property<String> OPENSSH_EXTENSIONS
|
||||
= Property.string("sftp-openssh-extensions");
|
||||
|
||||
/**
|
||||
* Comma separate list of {@code SSH_ACL_CAP_xxx} names - where name can be without the prefix. If not defined then
|
||||
* {@link AbstractSftpSubsystemHelper#DEFAULT_ACL_SUPPORTED_MASK} is used
|
||||
* Comma separate list of {@code SSH_ACL_CAP_xxx} names - where name can be without the prefix.
|
||||
*/
|
||||
public static final Property<String> ACL_SUPPORTED_MASK
|
||||
= Property.string("sftp-acl-supported-mask");
|
||||
|
@ -152,7 +125,7 @@ public final class SftpModuleProperties {
|
|||
= Property.string("sftp-newline", IoUtils.EOL);
|
||||
|
||||
/**
|
||||
* Force the use of a max. packet length for {@link AbstractSftpSubsystemHelper#doRead(Buffer, int)} protection
|
||||
* Force the use of a max. packet length for protection
|
||||
* against malicious packets
|
||||
*/
|
||||
public static final Property<Integer> MAX_READDATA_PACKET_LENGTH
|
||||
|
@ -187,9 +160,6 @@ public final class SftpModuleProperties {
|
|||
/**
|
||||
* Max. rounds to attempt to create a unique file handle - if all handles already in use after these many rounds,
|
||||
* then an exception is thrown
|
||||
*
|
||||
* @see SftpSubsystem#generateFileHandle(Path)
|
||||
* @see #DEFAULT_FILE_HANDLE_ROUNDS
|
||||
*/
|
||||
public static final Property<Integer> MAX_FILE_HANDLE_RAND_ROUNDS
|
||||
= Property.validating(
|
||||
|
@ -200,8 +170,7 @@ public final class SftpModuleProperties {
|
|||
});
|
||||
|
||||
/**
|
||||
* Maximum amount of data allocated for listing the contents of a directory in any single invocation of
|
||||
* {@link SftpSubsystem#doReadDir(Buffer, int)}
|
||||
* Maximum amount of data allocated for listing the contents of a directory in any single invocation
|
||||
*/
|
||||
public static final Property<Integer> MAX_READDIR_DATA_SIZE
|
||||
= Property.integer("sftp-max-readdir-data-size", 16 * 1024);
|
||||
|
|
|
@ -36,7 +36,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import java.util.function.Function;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import org.apache.sshd.common.AttributeRepository;
|
||||
import org.apache.sshd.common.Closeable;
|
||||
import org.apache.sshd.common.FactoryManager;
|
||||
import org.apache.sshd.common.PropertyResolver;
|
||||
|
@ -100,7 +99,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements
|
|||
private int id = -1;
|
||||
private int recipient = -1;
|
||||
private Session sessionInstance;
|
||||
private CloseableExecutorService executor;
|
||||
private final CloseableExecutorService executor;
|
||||
private final List<RequestHandler<Channel>> requestHandlers = new CopyOnWriteArrayList<>();
|
||||
|
||||
private final Window localWindow;
|
||||
|
|
|
@ -704,7 +704,7 @@ public final class KeyUtils {
|
|||
* @param expected The expected fingerprint if {@code null} or empty then returns a failure with the default
|
||||
* fingerprint.
|
||||
* @param key the {@link PublicKey} - if {@code null} then returns null.
|
||||
* @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
|
||||
* @return SimpleImmutableEntry - key is success indicator, value is actual fingerprint,
|
||||
* {@code null} if no key.
|
||||
* @see #getDefaultFingerPrintFactory()
|
||||
* @see #checkFingerPrint(String, Factory, PublicKey)
|
||||
|
@ -718,7 +718,7 @@ public final class KeyUtils {
|
|||
* fingerprint.
|
||||
* @param f The {@link Factory} to be used to generate the default {@link Digest} for the key
|
||||
* @param key the {@link PublicKey} - if {@code null} then returns null.
|
||||
* @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
|
||||
* @return SimpleImmutableEntry - key is success indicator, value is actual fingerprint,
|
||||
* {@code null} if no key.
|
||||
*/
|
||||
public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(
|
||||
|
@ -731,7 +731,7 @@ public final class KeyUtils {
|
|||
* fingerprint.
|
||||
* @param d The {@link Digest} to be used to generate the default fingerprint for the key
|
||||
* @param key the {@link PublicKey} - if {@code null} then returns null.
|
||||
* @return SimpleImmutableEntry<Boolean, String> - key is success indicator, value is actual fingerprint,
|
||||
* @return SimpleImmutableEntry - key is success indicator, value is actual fingerprint,
|
||||
* {@code null} if no key.
|
||||
*/
|
||||
public static SimpleImmutableEntry<Boolean, String> checkFingerPrint(String expected, Digest d, PublicKey key) {
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.apache.sshd.common.util.security.SecurityUtils;
|
|||
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
|
||||
*/
|
||||
public abstract class AbstractResourceKeyPairProvider<R> extends AbstractKeyPairProvider {
|
||||
|
||||
private FilePasswordProvider passwordFinder;
|
||||
/*
|
||||
* NOTE: the map is case insensitive even for Linux, as it is (very) bad practice to have 2 key files that differ
|
||||
|
|
|
@ -165,7 +165,7 @@ public final class OsUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Remove {@code Windows} domain and/or group prefix as well as "(User);" suffix
|
||||
* Remove {@code Windows} domain and/or group prefix as well as "(User);" suffix
|
||||
*
|
||||
* @param user The original username - ignored if {@code null}/empty
|
||||
* @return The canonical user - unchanged if {@code Unix} O/S
|
||||
|
|
|
@ -63,13 +63,13 @@ public interface BufferPublicKeyParser<PUB extends PublicKey> {
|
|||
OpenSSHCertPublicKeyParser.INSTANCE));
|
||||
|
||||
/**
|
||||
* @param keyType The key type - e.g., "ssh-rsa", "ssh-dss"
|
||||
* @param keyType The key type - e.g., ssh-rsa, ssh-dss
|
||||
* @return {@code true} if this key type is supported by the parser
|
||||
*/
|
||||
boolean isKeyTypeSupported(String keyType);
|
||||
|
||||
/**
|
||||
* @param keyType The key type - e.g., "ssh-rsa", "ssh-dss"
|
||||
* @param keyType The key type - e.g., ssh-rsa, ssh-dss
|
||||
* @param buffer The {@link Buffer} containing the encoded raw public key
|
||||
* @return The decoded {@link PublicKey}
|
||||
* @throws GeneralSecurityException If failed to generate the key
|
||||
|
|
|
@ -78,10 +78,6 @@ public final class Builder implements ObjectBuilder<Closeable> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder sequential(Object id, Iterable<Closeable> closeables) {
|
||||
return close(new SequentialCloseable(id, lock, closeables));
|
||||
}
|
||||
|
||||
public Builder parallel(Closeable... closeables) {
|
||||
if (closeables.length == 1) {
|
||||
close(closeables[0]);
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.apache.sshd.common.util.closeable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import org.apache.sshd.common.Closeable;
|
||||
|
||||
/**
|
||||
|
@ -25,4 +27,12 @@ import org.apache.sshd.common.Closeable;
|
|||
*/
|
||||
public abstract class IoBaseCloseable implements Closeable {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
Closeable.close(this);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class SequentialCloseable extends SimpleCloseable {
|
|||
@Override
|
||||
protected void doClose(boolean immediately) {
|
||||
Iterator<? extends Closeable> iterator = closeables.iterator();
|
||||
SshFutureListener<CloseFuture> listener = new SshFutureListener<CloseFuture>() {
|
||||
SshFutureListener<CloseFuture> listener = new SshFutureListener<>() {
|
||||
@SuppressWarnings("synthetic-access")
|
||||
@Override
|
||||
public void operationComplete(CloseFuture previousFuture) {
|
||||
|
|
|
@ -76,7 +76,7 @@ public class DERWriter extends FilterOutputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
|
||||
* The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
|
||||
* positive
|
||||
*
|
||||
* @param bytes {@link BigInteger} bytes
|
||||
|
@ -87,7 +87,7 @@ public class DERWriter extends FilterOutputStream {
|
|||
}
|
||||
|
||||
/**
|
||||
* The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
|
||||
* The integer is always considered to be positive, so if the first byte is < 0, we pad with a zero to make it
|
||||
* positive
|
||||
*
|
||||
* @param bytes {@link BigInteger} bytes
|
||||
|
|
|
@ -111,7 +111,7 @@ public final class SecurityUtils {
|
|||
/**
|
||||
* The min. key size value used for testing whether Diffie-Hellman Group Exchange is supported or not. According to
|
||||
* <A HREF="https://tools.ietf.org/html/rfc4419">RFC 4419</A> section 3: "Servers and clients SHOULD support
|
||||
* groups with a modulus length of k bits, where 1024 <= k <= 8192". </code>
|
||||
* groups with a modulus length of k bits, where 1024 <= k <= 8192". </code>
|
||||
*
|
||||
* <B>Note: this has been amended by <A HREF="https://tools.ietf.org/html/rfc8270">RFC 8270</A>
|
||||
*/
|
||||
|
@ -384,7 +384,6 @@ public final class SecurityUtils {
|
|||
if (REGISTRATION_STATE_HOLDER.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String regsList = System.getProperty(SECURITY_PROVIDER_REGISTRARS,
|
||||
GenericUtils.join(DEFAULT_SECURITY_PROVIDER_REGISTRARS, ','));
|
||||
boolean bouncyCastleRegistered = false;
|
||||
|
@ -475,13 +474,11 @@ public final class SecurityUtils {
|
|||
if (parser == null) {
|
||||
throw new NoSuchProviderException("No registered key-pair resource parser");
|
||||
}
|
||||
|
||||
Collection<KeyPair> ids = parser.loadKeyPairs(session, resourceKey, provider, inputStream);
|
||||
int numLoaded = GenericUtils.size(ids);
|
||||
if (numLoaded <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,16 +19,27 @@
|
|||
|
||||
package org.apache.sshd.common.util.threads;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.sshd.common.Closeable;
|
||||
|
||||
public interface CloseableExecutorService extends ExecutorService, Closeable {
|
||||
|
||||
default boolean awaitTermination(Duration timeout) throws InterruptedException {
|
||||
Objects.requireNonNull(timeout, "No timeout specified");
|
||||
return awaitTermination(timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void close() {
|
||||
try {
|
||||
Closeable.close(this);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,6 @@ public class DavPropertyNameSet extends PropContainer
|
|||
* in order to successfully add the given entry.
|
||||
* @return true if contentEntry is an instance of <code>DavPropertyName</code>
|
||||
* that could be added to this set. False otherwise.
|
||||
* @see PropContainer#addContent(Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean addContent(PropEntry contentEntry) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
group = org.xbib
|
||||
name = files
|
||||
version = 4.0.0
|
||||
version = 4.1.0
|
||||
|
||||
org.gradle.warning.mode = ALL
|
||||
|
|
|
@ -2,21 +2,14 @@
|
|||
apply plugin: 'java-library'
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
modularity.inferModulePath.set(true)
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes('Implementation-Version': project.version)
|
||||
|
@ -24,7 +17,9 @@ jar {
|
|||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs.add('-Xlint:all,-exports')
|
||||
options.fork = true
|
||||
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
|
||||
options.compilerArgs.add('-Xlint:all')
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
3
gradle/wrapper/gradle-wrapper.properties
vendored
3
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,7 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
|
22
gradlew
vendored
22
gradlew
vendored
|
@ -83,7 +83,8 @@ done
|
|||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
@ -130,10 +131,13 @@ location of your Java installation."
|
|||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
|
@ -141,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
|
@ -149,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
|||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
|
@ -198,11 +202,11 @@ fi
|
|||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
|
|
|
@ -15,10 +15,10 @@ pluginManagement {
|
|||
dependencyResolutionManagement {
|
||||
versionCatalogs {
|
||||
libs {
|
||||
version('gradle', '8.1.1')
|
||||
version('gradle', '8.4')
|
||||
version('groovy', '4.0.12')
|
||||
version('junit', '5.9.3')
|
||||
version('net', '3.2.0')
|
||||
version('junit', '5.10.0')
|
||||
version('net', '4.0.0')
|
||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||
|
@ -27,8 +27,8 @@ dependencyResolutionManagement {
|
|||
library('junit4', 'junit', 'junit').version('4.13.2')
|
||||
library('net-security', 'org.xbib', 'net-security').versionRef('net')
|
||||
library('mockftpserver', 'org.mockftpserver', 'MockFtpServer').version('2.7.1')
|
||||
library('mockito-core', 'org.mockito', 'mockito-core').version('3.7.7')
|
||||
library('mockito-junit-jupiter', 'org.mockito', 'mockito-junit-jupiter').version('3.7.7')
|
||||
library('mockito-core', 'org.mockito', 'mockito-core').version('5.6.0')
|
||||
library('mockito-junit-jupiter', 'org.mockito', 'mockito-junit-jupiter').version('5.6.0')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue