Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Проблемы при работе с commons- vfs


Автор: LSD 31.1.2007, 14:02
Взаимодействие org.apache.commons.vfs и некоторых FTP серверов

Все FTP сервера, функционирующие в сетях или Интернет делятся на несколько типов в зависимости от типа файловой системы их жестких дисков. Такое разделение связано с типом операционной системы которая установлена на сервере. У операционных систем разных семейств  разные подходы к представлению данных на диске. Например в операционных системах семейства Unix разделительной чертой(сепаратором), с помощью которой формируются пути к файлам на диске является символ "/",
в Windows наоборот - "\". Поэтому клиент который обращается к фтп серверу должен знать какого типа  ФС сервера чтобы знать как правильно искать файлы, и передавать из пользователю.  Большинство серверов имеют тип файловой системы  Unix, многие сервера имеют тип файловой системы Windows есть также сервера со специфическими свойствами, касающимися взаимодействий с различными FTP клиентами. Чтобы клиент мог понять с каким сервером он имеет дело, сервер дает клиенту некоторые сведения о себе. Среди прочей информации сервер передает клиенту описание своей файловой системы. Если это Unix ФС то этим описанием будет что то вроде "UnixFS" или еще что то. Для серверов с ФС Windows этим описанием будет строка "WINDOWS" или что то в этом роде.
Чтобы правильно распознавать ФС и работать с файлами на ней существуют специальные средства-парсеры (англ. parse-анализ, разбор). Они отвечают за "понимание" файловой системы сервера и работу с ней. В пакете org.apache.commons.net, без которого не может работать org.apache.commons.vfs, и который отвечает за работу с сетевыми ресурсами, запрограммированы парсеры под самые распространенные типы файловых систем. Но как оказалось не под все.  
Файловая система с опианием Win32 A N оказалась "непонятной"  для пакета. А следовательно для этой ФС неприменим ни org.apache.commons.vfs. ни org.apache.commons.net. Что делать?
Рассмотрим пример.

Задача: скопировать папку с FTP сервера на локальный диск но с помощью org.apache.commons.vfs так как на мой взгляд это элегантное и функциональное решение.
FTP Сервер: Small HTTP Server. Я использую его для тестирования многие годы. Ничего лучше я пока не видел.
FTP Клиент: Простое консольное Java приложение. Его исходный код:
Код

import org.apache.commons.vfs.*;
import org.apache.commons.logging.*;
import java.io.*;
class test{
  public static void main(String[] args){
    try{
      FileSystemManager man=VFS.getManager();
      FileObject f1=man.resolveFile("C:\\Dir2\\Dir");
      FileObject f2=man.resolveFile("ftp://root:root@test/test");
      f1.copyFrom(f2,Selectors.SELECT_ALL);
    }
    catch(FileSystemException e){
    System.out.println("privet="+e.toString());
    }
  }
}

При попытке запустить этот код возникает ошибка:
Код

Exception in thread "main" org.apache.commons.net.ftp.parser.ParserInitializationException: Unknown parser type: WIN32 A N
        at org.apache.commons.net.ftp.parser.DefaultFTPFileEntryParserFactory.createFileEntryParser(DefaultFTPFileEntryParserFa
tory.java:118)
        at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:2358)
        at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:2141)
        at org.apache.commons.vfs.provider.ftp.FTPClientWrapper.listFiles(FTPClientWrapper.java:112)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.doGetChildren(FtpFileObject.java:123)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.getChildFile(FtpFileObject.java:103)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.getInfo(FtpFileObject.java:181)
        at org.apache.commons.vfs.provider.ftp.FtpFileObject.refresh(FtpFileObject.java:208)
        at org.apache.commons.vfs.provider.AbstractFileSystem.resolveFile(AbstractFileSystem.java:319)
        at org.apache.commons.vfs.provider.AbstractFileSystem.resolveFile(AbstractFileSystem.java:267)
        at org.apache.commons.vfs.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:88)
        at org.apache.commons.vfs.provider.AbstractOriginatingFileProvider.findFile(AbstractOriginatingFileProvider.java:62)
        at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:641)
        at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:602)
        at org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:570)
        at test.main(test.java:13)


Ключевая фраза в последнем фрагменте:
Цитата

Unknown parser type: WIN32 A N


Решение:

1) У нас есть http://apache.easy-webs.de/jakarta/commons/net/source/commons-net-1.4.1-src.zip
2)Скачиваем распаковываем, берем оттуда файл DefaultFTPFileEntryParserFactory.java
3)Открываем и правим: находим строку 
Код

else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0)

меняем ее на
Код

else if (ukey.indexOf(FTPClientConfig.SYST_NT) >= 0 || ukey.indexOf("WIN32 A N") >= 0) 

4)Компилируем класс 
5)У нас есть http://apache.easy-webs.de/jakarta/commons/net/binaries/commons-net-1.4.1.zip, распаковываем, заходим в jar архив, и соответственно меняем класс DefaultFTPFileEntryParserFactory.class на аналогичный только что скомпиленный. 
6) Выходим из jar архива, кидаем его в  CLASSPATH, все как обычно.
Готово. Теперь наш пакет понимает сервера с файловой системой обозначаемой WIN32 A N и код прекрасно работает с прекрасным Small Http Server `ом. Это было описание того что проделано для понимания. Если же кто то не хочет возиться с переделыванием, можно взять готовый  jar архив http://forum.vingrad.ru/index.php?act=module&module=vingradfaq&target=download_file&articleid=3089&attachid=1

Автор статьи: http://forum.vingrad.ru/index.php?showuser=777&nickname=zone51

Благодарности: http://forum.vingrad.ru/index.php?showuser=777&nickname=w1nd, который собственно и является автором идеи.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)