Skip to content

Managed File Toolbox

Operações de I/O são consideradas muitas vezes limítrofes e menos importantes, contudo são as mais frequentemente usadas e são quase onipresentes em todos os tipos de aplicações. Aplicações web, por exemplo, precisam com frequência trabalhar com arquivos carregados (upload) e descarregados ( download) os quais acabam indo parar no sistema de arquivos do OS. Normalmente esta funcionalidade é conseguida usando uma API de terceiros ( nomeadamente a Commons-Fileupload) e o verdadeiro trabalha reduz-se a trabalho de canalização de fluxos  de dados (streams). Isso não é divertido e lá pela segunda vez que você faz isso, é bem chato.

A Managed File Toolbox  é uma parte essencial do MiddleHeaven. Muitas outras toolboxes a usam para lidar com dados tipo arquivo ou fluxo de dados de forma transparente. Veremos detalhes de como quando falarmos de cada uma. Primeiro vejamos os conceitos básicos que forma esta toolbox.

A plataforma Java permite a manipulação de arquivos através do uso de três classes principais java.io.File, java.io.FileInputstream e java.io.FileOutputstream. Por outro lado, é possível tratar arquivos comprimidos em zip , jar  e tar. Contudo não é possível tratar um arquivo comprimido como uma pasta, iterar os seus arquivos internos, etc…

A biblioteca Commons-Upload da Apache Fundation é uma das mais usadas ( senão a única) para trabalhar com upload de arquivos em sites. Esta biblioteca permite listar e ler o conteúdo do arquivo, mas não tem nenhum conceito de sistema de arquivos.

A biblioteca Commons-VFS (Virtual File System) usa a ideia de arquivos e sistemas de arquivos virtuais e permite que arquivos em diferentes localizações físicas sejam tratados com a mesma API. Contudo, embora suporte o tratamento de arquivos comprimidos como pastas, não o faz  transparentemente. Por outro lado,  não se integra com a Commons-Upload.

A ideia de sistema de arquivos virtual não é nova e o que a Managed File Toolbox representa é a aceitação de que esse conceito é necessário para construir uma plataforma de execução encapsulada como o MiddleHeaven pretende ser. Outras plataformas utilizam esta ideia, por exemplo, o Windows XP apresenta arquivos comprimidos me zip como pastas e é possível explorar o conteúdo do arquivo como se fosse uma pasta. Esta é uma das possibilidades de um sistema de arquivos virtual.

Em cima disso o MiddleHaeaven oferece ainda a possibilidade de integrar o upload e download de arquivos e o tratamento de um HTTP response como se fosse um arquivo ( na realidade é). Outras opções são o tratamento de arquivos em FTP.

File vs Managed File

Um ManagedFile é um nodo em um sistema de arquivos tal como o java.io.File. A diferença é que enquanto o java.io.File representa um nodo no sistema de arquivos da máquina local, o ManagedFile representa um nodo em um sistema de arquivos virtual, ou seja, não necessariamente o da máquina local, não necessariamente local, e não necessariamente fora da memória onde a aplicação roda.

Para ler e escrever um java.io.File temos que criar InputStrem e OutputStream,  respectivamente. O uso de streams é uma forma consagrada para trabalhar com I/O e o objetivo não é alterar isso. O objectivo é simplificar a obtenção de streams de leitura e escrita para os arquivos. Sendo que os arquivos são virtuais e apenas eles mesmos sabem onde se localizam os dados reais, do ManagedFile é possivel obter um ManagedFileContent  a partir do qual podemos obter os streams de leitura e escrita.

Cópia de arquivos é algo que a plataforma Java deixou ao critério do programador. Uma boa razão para isso é que não existe uma única , melhor, forma de o fazer. Todos os ManagedFile contam com o método copyTo() que permite a copia simples do conteúdo de um arquivo para outro, ou para uma pasta. Este processo é otimizado com o uso de NIO quando os arquivos são baseados em java.io.File ( ou seja, presentes na máquina local).

As raízes para os sistemas virtuais são recursos que normalmente não são vistos como sistemas de arquivos, ou , sequer, como arquivos ( um URL, por exemplo).

Outra operação interessante que não existe na plataforma Java padrão ( embora se fale que irá existir na versão 7) é a capacidade de observar arquivos. A ideia é que seja gerado um evento quando se detecta que um arquivo foi alterado. Várias funcionalidades interessantes podem ser montadas em cima disto e o MiddleHeaven usa esta funcionalidade, por exemplo, para o preenchimento automático e dinâmico do contexto de injeção de objetos

Dito isto, é importante entender que logo no inicialização do MiddleHeaven é determinada a localização onde o programa está rodando. Isso e algumas considerações que faremos na Core : Boostrap Toolbox permitem que a aplicação acesse arquivos sem saber exatamente onde eles ficam localizados.

Modelo

A f igura abaixo ilustra os elementos básicos na Managed File Toolbox no MiddleHeaven.

Ilustration 1: Managed file main types

O ManagedFile é o tipo principal. Dele é possível obter os arquivos filho, pastas ou ter acesso ao arquivo pai. É possível também obter o ManagedFileContent de onde se obtêm os streams de leitura e escrita para os dados em si.

Quase todas as operações lançam ManagedIOException que é uma versão não verificada e de IOException. Melhores práticas de tratamento de exceções indicam que todas as exceções lançadas por subsistemas devem ser encapsuladas pela camada que os acessa. E no caso, a politica de exceções do MiddleHeaven é usar exceções não-verificadas sempre que possível ( existem alguns circunstancias onde é necessário usar exceções verificadas, mas não é o caso desta toolbox). O MiddleHeaven incorpora o padrão Exception Handler do qual o método ManagedIOException.manage() é uma implementação padrão que traduz exceções IOException e suas filhas nas suas contrapartes filhas de ManagedIOException ( por exemplo, FileNotFoundException é mapeada para FileNotFoundManagedException com o bônus de que FileNotFoundManagedException  contém o caminho do arquivo que não foi encontrado como uma propriedade da exceção que pode ser usada para um controle mais fino de excções ou um melhor registro de exceções)

ManagedFile tem ainda o método isWatchable que normalmente retorna false. Por contrato ele só pode retornar true se o objeto implementar também WatchableRepository. A class WatchableRepository provê a capacidade de obervação “cão de guarda” que avisa todos os FileChangeListener registrados através de evento quando o arquivo foi laterado.

Embora managedFile seja o principal contrato para utilizadores da toolbox, o contrato de ManagedFileResolver é o mais relevante para a implementação da toolbox em si. Porque a toobox deve interoperar com diferentes tipos de sistemas semelhantes a sistemas de arquivos o MiddleHeaven incluindo uma camada de abstração chamada de “motor” (engine) representada pela interface RepositoryEngine . Deferentes motores proveem diferentes ManagedFileResolver que por sua vez conseguem mapear diferentes recursos para um sistema virtual de arquivos.

Uso

Usar ManagedFile é muito simples. Neste exemplo criamos um arquivo vazio na pasta corrente e localizamos o jar JUnit.jar no repositório local do maven. Por fim copiamos esse jar para o arquivo que criamos e listamos os arquivos dentro dele. Veremos também como obter um ManagedFile a partir de um java.io.File ( é bom lembrar que ao usar o MiddleHeaven você nunca irá fazer isto, mas ao extender a ManagedFile toolbox é bem provável que precise fazê-lo)

01
02 //ManagedFileRepositories is an integration utilities class that allows
03 // for integration with java.io.File and others
04
05 ManagedFile folder = ManagedFileRepositories.resolveFile ( new File ( “.” )) ;
06
07 assertTrue ( folder.exists ()) ;
08
09 // resolving is simply acquiring a location where the file should be.
10 ManagedFile testJar = folder.resolveFile ( “test.jar” ) ;
11
12 // if exists, delete it.
13 if ( testJar.exists ()){
14 testJar.delete () ;
15 }
16
17 // create a new (empty) file
18 testJar = testJar.createFile () ;
19
20 // it must exist by now
21 assertTrue ( testJar.exists ()) ;
22
23 // manually obtain the path to the repository
24 ManagedFile rep = ManagedFileRepositories.resolveFile ( new File ( System.getProperty ( “user.home” ) + “/.m2/repository/junit/junit/4.1” )) ;
25
26 // resolve the file
27 ManagedFile junitJar = rep.resolveFile ( “junit-4.1.jar” ) ;
28
29 // copy it to the location previous created
30 junitJar.copyTo ( testJar ) ;
31
32 // this a jar file that contains other files. So listFiles() collection will not be empty
33 assertFalse ( junitJar.listFiles () .isEmpty ()) ;
34
35

Codigo 1: Exemplo de uso de ManagedFile

Este exemplo mostrar como podemos abstrair um java.io.File para um ManagedFile e como é simples copiar arquivos entre localizações invocando copyTo(). Finalmente apresentamos um exemplo simples para ilustrar o poder de um sistema virtual de arquivos ao ler quantos arquivos existem dentro do jar. O mesmo funcionaria para arquivos zip.

Por detrás dos panos

Já tinha usado o conceito de um sistema virtual em outros frameworks que desenvolvi, mas nunca de forma formal , ou  seja, como uma camada sólida e independente. Durante esse tempo cruzei-me como a  Commons VFS da Apache que é basead na mesma ideia de arquivo virtual.  A MaangedFile toolbox é um bom exemplo dos objetivos do MiddleHeaven. No principio a implementação era apenas em cima de java.io.File e da Commons Upload para trabalhar com arquivos enviados de páginas web. A ideia do zip estava lá, mas nunca cheguei e era possível usando as classes de manipulação de zip da plataforma. Ao descobrir a Commons VFS não foi necessário mais implementar esses outro sistemas virtuais e uma simples adaptação da Commons VFS permitiu expandir o uso do ManagedFile toolbox da noite para o dia. Contudo, devido ao sistema de motores, a implementação baseada na Commons VFS só é carregada se o seu jar estiver presente no classpath. Caso contrário a API baseada em java.io.File é usada. Isto é interessante já que a maioria das vezes você não estará trabalhando como arquivos jar ou FTP.  O melhor de todos os mundos é alcançado de maneira muito simples graças a um design feito pensando em expansão e encapsulamento. É por isso que esta toolbox ilustra bem o objetivo do MiddleHeaven. É possível utilizar o sistema de arquivos nativo (o mesmo usado porjava.io.File) , sistema de arquivos de upload em ambiente web, e através da Commons VFS muitos outros. O interessante é usar duas bibliotecas da Commons e integrá-las transparentemente.  No futuro a ideia é implementar versões próprias  para comunicação como os vários sistemas de arquivos de forma a limpar o classpath da Commons e suas dependências.

4 comentários
  1. Gostei desta ideia de arquivos virtuais.

    Quanto ao projeto, é uma ideia bem interessante. Com relação a distruibuição e uso, como será feito quanto o projeto estiver concluido, ou com uma versão estavel ?

    Parabens

    • sergiotaborda permalink

      A ideia para a distribuição quando o estiver completo é ter um jar para o core e as toolbox opcionais à parte ( por exemplo gráficos ou relatórios) . Por agora , e nas primeiras versões estáveis será um jar só.
      Além disso, serão necessários os jars das bibliotecas em que o MH se baseia como o Common-Upload e outras. A diferença é que a maioria dessas é opcional e apenas necessária quando é usada. Por exemplo, se não está usando web, o commons-upload não será necessário.

  2. ler todo o blog, muito bom

Trackbacks & Pingbacks

  1. Anónimo

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: