apache VFS2 uriStyle - абсолютный путь root заканчивается двойной косой чертой

Во время работы на ftp-сервере с библиотекой vfs2 я заметил, что мне пришлось включить VFS.setUriStyle(true), чтобы библиотека сменила рабочий каталог на родительский каталог целевого файла, с которым я работаю (cwd directoryName).

Но если UriStyle включен, все решается относительно корня. Что не было бы проблемой, если бы корень не был "//".

Класс GenericFileName устанавливает absolutePath корня в "/", что заставляет метод getPath() возвращать "/"+getUriTrailer(), который в случае корня всегда возвращает "//". Все, что разрешено относительно //, имеет две точки, идущие к их пути.

Это означает, что если я выполню следующий код:

public class RemoteFileTest {
public static void main(String[] args) {
    // Options for a RemoteFileObject connection
    VFS.setUriStyle(true);
    FileSystemOptions options = new FileSystemOptions();
    // we doing an ftp connection, hence we use the ftpConfigBuilder
    // we want to work in passive mode
    FtpFileSystemConfigBuilder.getInstance().setPassiveMode(options, true);
    FtpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(options, false);
    // DefaultFileSystemConfigBuilder.getInstance().setRootURI(options, "/newRoot/");
    // System.out.println(DefaultFileSystemConfigBuilder.getInstance().getRootURI(options));
    // ftp://localhost:21/

    StaticUserAuthenticator auth = new StaticUserAuthenticator("", "user", "pass");
    try {
        DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(options, auth);
    } catch (FileSystemException e) {
        e.printStackTrace();
        return;
    }

    // A FileSystemManager creates an abstract FileObject linked to are desired RemoteFile.
    // That link is just simulated and not yet real.
    FileSystemManager manager;
    try {
        manager = VFS.getManager();
    } catch (FileSystemException e) {
        e.printStackTrace();
        return;
    }

    try (FileObject remoteFile = manager.resolveFile("ftp://localhost:21/sub_folder/test.txt", options)) {

        System.out.println("Is Folder " + remoteFile.isFolder());
        System.out.println("Is File " + remoteFile.isFile());

    } catch (FileSystemException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return;
    }

}}

Я получаю это взаимодействие с сервером ftp:

USER user
PASS ****
TYPE I
CWD //
SYST
PASV
LIST ..sub_folder/
PWD
CWD ..sub_folder/

Я хочу, чтобы взаимодействие было таким же, но без двух точек перед каталогом.

С наилучшими пожеланиями Барри

1 ответ

Исправлено, как описано ниже:

Снова отключил uriStyle. Написал свой собственный класс VFS, который создает мой собственный написанный менеджер. Этот менеджер перезаписывает FtpFileProvider моим пользовательским, который просто устанавливает корень на пользовательский, выбранный, что вызывает желаемое поведение.

import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystem;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs2.provider.ftp.FtpFileProvider;

public class AdvancedFtpFileProvider extends FtpFileProvider {
    public AdvancedFtpFileProvider() {
        super();
        // setFileNameParser(AdvancedFtpFileNameParser.getInstance());
    }

    @Override
    protected FileObject findFile(FileName name, FileSystemOptions fileSystemOptions) throws FileSystemException {
        // Check in the cache for the file system
        //getContext().getFileSystemManager().resolveName... resolves the configured RootUri relative to the selected root (name.getRoot()). This calls cwd to the selectedRoot and operates from there with relatives urls towards the new root!
        final FileName rootName = getContext().getFileSystemManager().resolveName(name.getRoot(), DefaultFileSystemConfigBuilder.getInstance().getRootURI(fileSystemOptions));

        final FileSystem fs = getFileSystem(rootName, fileSystemOptions);

        // Locate the file
        // return fs.resolveFile(name.getPath());
        return fs.resolveFile(name);
    }
}

Наткнулся на этот вопрос, потому что у меня была такая же проблема со следующим

ftp://user:pass@host//home/user/file.txt

становится... (обратите внимание на один слеш после "дома")

ftp://user:pass@host/home/user/file.txt

Я сделал это, чтобы решить проблему...

// Setup some options, add as many as you need    
FileSystemOptions opts = new FileSystemOptions( );

// This line tells VFS to treat the URI as the absolute path and not relative
FtpsFileSystemConfigBuilder.getInstance( ).setUserDirIsRoot( opts, false );

// Retrieve the file from the remote FTP server    
FileObject realFileObject = fileSystemManager.resolveFile( fileSystemUri, opts );

Я надеюсь, что это может помочь кому-то, если нет, то предоставьте ссылку на следующий раз, когда это ставит меня в тупик.

Другие вопросы по тегам