// Path: src/test/java/com/github/robtimus/filesystems/sftp/server/FixedSftpSubsystem.java
// @SuppressWarnings("javadoc")
// public class FixedSftpSubsystem extends SftpSubsystem {
// 
//     public FixedSftpSubsystem(ExecutorService executorService, boolean shutdownOnExit, UnsupportedAttributePolicy policy,
//             SftpFileSystemAccessor accessor, SftpErrorStatusDataHandler errorStatusDataHandler) {
//         super(executorService, shutdownOnExit, policy, accessor, errorStatusDataHandler);
//     }
// 
//     @Override
//     protected Map<String, Object> doStat(int id, String path, int flags) throws IOException {
//         Path p = resolveFile(path);
//         return resolveFileAttributes(p, flags, IoUtils.getLinkOptions(true));
//     }
// 
//     public static final class Factory extends SftpSubsystemFactory {
// 
//         @Override
//         public Command create() {
//             SftpSubsystem subsystem = new FixedSftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy(),
//                     getFileSystemAccessor(), getErrorStatusDataHandler());
//             Collection<? extends SftpEventListener> listeners = getRegisteredListeners();
//             if (GenericUtils.size(listeners) > 0) {
//                 for (SftpEventListener l : listeners) {
//                     subsystem.addSftpEventListener(l);
//                 }
//             }
// 
//             return subsystem;
//         }
//     }
// 
//     public static final class FactoryWithoutSystemDirs extends SftpSubsystemFactory {
// 
//         @Override
//         public Command create() {
//             SftpSubsystem subsystem = new FixedSftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy(),
//                     getFileSystemAccessor(), getErrorStatusDataHandler());
//             Collection<? extends SftpEventListener> listeners = getRegisteredListeners();
//             if (GenericUtils.size(listeners) > 0) {
//                 for (SftpEventListener l : listeners) {
//                     subsystem.addSftpEventListener(l);
//                 }
//             }
//             subsystem.addSftpEventListener(new AbstractSftpEventListenerAdapter() {
//                 @Override
//                 public void open(ServerSession session, String remoteHandle, Handle localHandle) {
//                     if (localHandle instanceof DirectoryHandle) {
//                         DirectoryHandle directoryHandle = (DirectoryHandle) localHandle;
//                         directoryHandle.markDotSent();
//                         directoryHandle.markDotDotSent();
//                     }
//                 }
//             });
// 
//             return subsystem;
//         }
//     }
// }


import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.spy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystemException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import com.github.robtimus.filesystems.sftp.server.FixedSftpSubsystem;
import com.jcraft.jsch.SftpException;

    protected final SFTPFileSystem fileSystem = sftpFileSystem;
    protected final SFTPFileSystem fileSystem2 = sftpFileSystem2;

    private static PublicKey readPublicKey(String resource) {
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            try (InputStream input = AbstractSFTPFileSystemTest.class.getResourceAsStream(resource)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = input.read(buffer)) != -1) {
                    output.write(buffer, 0, len);
                }
            }
            // public key parsing based on https://gist.github.com/destan/b708d11bd4f403506d6d5bb5fe6a82c5
            String publicKeyContent = new String(output.toString("UTF-8"))
                    .replace("\\n", "")
                    .replace("-----BEGIN PUBLIC KEY-----", "")
                    .replace("-----END PUBLIC KEY-----", "");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(publicKeyContent));
            return keyFactory.generatePublic(keySpec);

        } catch (IOException | GeneralSecurityException e) {
            throw new IllegalStateException(e);
        }
    }

    @BeforeAll
    static void setupClass() throws NoSuchAlgorithmException, IOException {
// Path: src/test/java/com/github/robtimus/filesystems/sftp/server/FixedSftpSubsystem.java
// @SuppressWarnings("javadoc")
// public class FixedSftpSubsystem extends SftpSubsystem {
// 
//     public FixedSftpSubsystem(ExecutorService executorService, boolean shutdownOnExit, UnsupportedAttributePolicy policy,
//             SftpFileSystemAccessor accessor, SftpErrorStatusDataHandler errorStatusDataHandler) {
//         super(executorService, shutdownOnExit, policy, accessor, errorStatusDataHandler);
//     }
// 
//     @Override
//     protected Map<String, Object> doStat(int id, String path, int flags) throws IOException {
//         Path p = resolveFile(path);
//         return resolveFileAttributes(p, flags, IoUtils.getLinkOptions(true));
//     }
// 
//     public static final class Factory extends SftpSubsystemFactory {
// 
//         @Override
//         public Command create() {
//             SftpSubsystem subsystem = new FixedSftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy(),
//                     getFileSystemAccessor(), getErrorStatusDataHandler());
//             Collection<? extends SftpEventListener> listeners = getRegisteredListeners();
//             if (GenericUtils.size(listeners) > 0) {
//                 for (SftpEventListener l : listeners) {
//                     subsystem.addSftpEventListener(l);
//                 }
//             }
// 
//             return subsystem;
//         }
//     }
// 
//     public static final class FactoryWithoutSystemDirs extends SftpSubsystemFactory {
// 
//         @Override
//         public Command create() {
//             SftpSubsystem subsystem = new FixedSftpSubsystem(getExecutorService(), isShutdownOnExit(), getUnsupportedAttributePolicy(),
//                     getFileSystemAccessor(), getErrorStatusDataHandler());
//             Collection<? extends SftpEventListener> listeners = getRegisteredListeners();
//             if (GenericUtils.size(listeners) > 0) {
//                 for (SftpEventListener l : listeners) {
//                     subsystem.addSftpEventListener(l);
//                 }
//             }
//             subsystem.addSftpEventListener(new AbstractSftpEventListenerAdapter() {
//                 @Override
//                 public void open(ServerSession session, String remoteHandle, Handle localHandle) {
//                     if (localHandle instanceof DirectoryHandle) {
//                         DirectoryHandle directoryHandle = (DirectoryHandle) localHandle;
//                         directoryHandle.markDotSent();
//                         directoryHandle.markDotDotSent();
//                     }
//                 }
//             });
// 
//             return subsystem;
//         }
//     }
// }


// Path: src/test/java/com/github/robtimus/filesystems/sftp/AbstractSFTPFileSystemTest.java
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.spy;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystemException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory;
import org.apache.sshd.common.keyprovider.MappedKeyPairProvider;
import org.apache.sshd.server.SshServer;
import org.apache.sshd.server.session.ServerSession;
import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import com.github.robtimus.filesystems.sftp.server.FixedSftpSubsystem;
import com.jcraft.jsch.SftpException;


    protected final SFTPFileSystem fileSystem = sftpFileSystem;
    protected final SFTPFileSystem fileSystem2 = sftpFileSystem2;

    private static PublicKey readPublicKey(String resource) {
        try {
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            try (InputStream input = AbstractSFTPFileSystemTest.class.getResourceAsStream(resource)) {
                byte[] buffer = new byte[1024];
                int len;
                while ((len = input.read(buffer)) != -1) {
                    output.write(buffer, 0, len);
                }
            }
            // public key parsing based on https://gist.github.com/destan/b708d11bd4f403506d6d5bb5fe6a82c5
            String publicKeyContent = new String(output.toString("UTF-8"))
                    .replace("\\n", "")
                    .replace("-----BEGIN PUBLIC KEY-----", "")
                    .replace("-----END PUBLIC KEY-----", "");
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getMimeDecoder().decode(publicKeyContent));
            return keyFactory.generatePublic(keySpec);

        } catch (IOException | GeneralSecurityException e) {
            throw new IllegalStateException(e);
        }
    }

    @BeforeAll
    static void setupClass() throws NoSuchAlgorithmException, IOException {
        setupClass(new FixedSftpSubsystem.Factory());