Java a rozšířené atributy souborů

Java ve své sedmé verzi přinese řadu zajímavých vlastností. Jednou z nich je i podpora práce s rozšířenými atributy souborů, což je funkcionalita poskytovaná souborovým systémem, která umožňuje k souborům ukládat metadata. V dnešním článku si povíme obecně o rozšířených atributech a ukážeme jak s nimi snadno pracovat v Javě (díky OpenJDK 7).

25.1.2011 00:00 | František Kučera | přečteno 14613×

Co jsou rozšířené atributy

Rozšířené atributy jsou funkcí souborového systému (např. ext2, ext3, ext4, JFS, ReiserFS, XFS a Btrfs) a umožňují nám k souborům ukládat metadata ve formě klíč-hodnota. Můžeme si tak k souborům přidávat různé popisy, poznámky nebo třeba uvést kódování znaků. A to vše bez ohledu na interní formát daného souboru a jeho možnosti.

Výhoda oproti metadatům uvnitř souborů: formáty jako např. MP3, JPEG a řada dalších umožňují ukládat metadata přímo do souboru (např. název písničky nebo datum vyfocení). Každý formát má ale vlastní způsob zápisu metadat a pro práci s nimi obvykle potřebujeme nějakou speciální knihovnu. Rozšířené atributy oproti tomu přinášejí standardní API pro práci s metadaty, které je nezávislé na konkrétním formátu. Např. název, autora nebo kódování si přečteme vždy stejným způsobem, ať už se jedná o písničku, obrázek nebo třeba textový dokument.

Výhoda oproti metadatům ve zvláštních souborech: metadata můžeme ukládat mimo vlastní soubor, to se používá třeba v případě kontrolního součtu nebo elektronického podpisu. Vždy musíme dávat pozor, abychom přenesli oba (všechny) soubory a nezapomněli je také správně přejmenovat. S rozšířenými atributy se nám to nestane, tam jsou metadata a vlastní soubor nerozlučně spjaty a při přesouvání nebo přejmenování nemusíme nic řešit – metadata se nám neztratí.

Nevýhoda: rozšířené atributy musí být podporované daným souborovým systémem. Když soubory nahrajeme třeba na disketu nebo flashku s nějakým primitivním FS, o metadata bohužel přijdeme. Totéž by se dalo říct o přenosech po síti. Jenže tam je situace spíš opačná – při přenosu souborů po HTTP nebo e-mailem (SMTP a MIME) se např. informace o MIME typu souboru nebo jeho kódování úspěšně přenáší (pomocí hlaviček příslušných protokolů/formátů) a ztratí se často až ve chvíli uložení souboru na disk. Proto je důležité si rozšířené atributy zapnout a používat je.

Abychom rozšířené atributy mohli používat, zkontrolujeme si v souboru /etc/fstab, že tam máme volbu user_xattr, případně ji přidáme (pak je potřeba znovu připojit souborový systém např. pomocí mount -o remount -a).

Nejvíce nás budou asi zajímat uživatelské atributy, ty se nacházejí ve jmenném prostoru user, ale existují i další: system, security nebo trusted.

Pro vyzkoušení rozšířených atributů si nainstalujeme nástroj pro příkazovou řádku: balíček attr. Pomocí příkazů getfattr, setfattr, případně attr můžeme atributy číst a zapisovat.

Rozšířené atributy podporuje i program curl – pomocí příkazu:

curl http://www.linuxsoft.cz/ --xattr --output ls.html

si stáhneme stránku z webu a curl nám k souboru přidá dva rozšířené atributy:

To je velice užitečné, protože často se stává, že si stáhneme nějaké materiály z webu a pak zapomeneme, odkud to bylo a později pracně hledáme původní zdroj. U kódování bývá podobný problém – zatímco při načítání z webu prohlížeč zjistí kódování z HTTP hlaviček, při načítání z disku tyto hlavičky chybí a prohlížeč musí kódování buď uhádnout, nebo ho hledat uvnitř souboru.

Pro program wget existují minimálně dva patche: jeden napsal Petr Písař a druhý Stefan Tomanek takže i při stahování tímto programem si můžete ukládat rozšířené atributy.

Standardy a doporučení

Abychom se vzájemně domluvili a nepoužíval každý svoje vlastní nekompatibilní názvy atributů, je dobré dodržovat nějaké konvence. Freedesktop.org radí, aby atributy specifické pro konkrétní aplikaci obsahovaly předponu – např.:

user.nějakáMojeAplikace.nějakýAtribut = "hodnota atributu"

Tím se předejde konfliktům v názvech. Pak existují společné atributy používané různými programy:

a navržené atributy jako jsou:

a další. Kromě toho můžeme autributy pojmenovat podle standardu Dublin Core – např.:

Simple Dublin Core Metadata Element Set definuje celkem 15 elementů.

Jak vidíme, možností je spousta. Pro začátek bude dobré ukládat k souborům alespoň jejich MIME typ a kódování znaků.

Práce s rozšířenými atributy v Javě

V současné době se chystá sedmá verze Javy, resp JDK 7, ve které bude spousta zajímavých novinek. Kromě jiného se můžeme těšit i na JSR 203: More new I/O APIs for the Java platform (NIO.2) A nemusíme se jen těšit, můžeme ho rovnou používat – vývojové verze OpenJDK 7 už jsou poměrně dost funkční.

V novém API se setkáváme s abstraktní třídou java.nio.file.Path jejíž instance představují soubor (nemusí nutně existovat). Jedná se o nástupce dříve používaného java.io.File, který všichni dobře známe. Když ve svém programu máme soubor, jednoduše z něj získáme cestu:

File soubor = new File("/cesta/k/souboru.txt");
Path cesta = soubor.toPath();

Nebo si vytvoříme cestu rovnou:

Path cesta = Paths.get("/cesta/k/souboru.txt");

Jakmile máme instanci Path, otevírají se nám možnosti nového API. Protože nás teď zajímají rozšířené atributy, vytvoříme si na ně pohled:

UserDefinedFileAttributeView pohled = cesta.getFileAttributeView(UserDefinedFileAttributeView.class);

Protože jsme zvolili UserDefinedFileAttributeView, pracujeme nad uživatelskými atributy (ne systémovými viz výše), tudíž se pohybujeme pořád ve jmenném prostoru user. Při práci s atributy teď tedy nepoužíváme předponu user – o to se postará Java. Z pohledu získáme seznam atributů daného souboru.

List<String> jménaAtributů = pohled.list();

Hodnoty jednotlivých atributů si načteme přes ByteBuffer:

for (String jménoAtributu : jménaAtributů) {
	ByteBuffer hodnotaAtributu = ByteBuffer.allocate(pohled.size(jménoAtributu));
	pohled.read(jménoAtributu, hodnotaAtributu);
	System.out.println(jménoAtributu + " = "  + dekóduj(hodnotaAtributu));
}

Pro převod bajtů na text použijeme následující metodu:

private static String dekóduj(ByteBuffer bajty) {
	bajty.flip();
	return Charset.defaultCharset().decode(bajty).toString();
}

Zápis atributu je opět jednoduchý – jen musíme zase převést textovou hodnotu zpátky na bajty:

pohled.write("názevAtributu", zakóduj("hodnota atributu"));

Kompletní funkční příklad najdete ve zdrojových kódech ukázkové aplikace – viz níže.

Toto API využijeme např. když budeme programovat souborové servelety – pak nemusíme MIME typ hádat podle přípony nebo prvních bajtů v souboru a jednoduše si ho přečteme z atributů (za předpokladu, že je tam uložený, samozřejmě). Nebo když budeme vyvíjet nějaký CMS – budeme mít metadata a soubory těsně spjaté a nebudeme muset řešit synchronizaci a referenční integritu mezi databází a souborovým systémem. Rozšířené atributy můžeme využít i k ošetření přístupových práv na úrovni aplikace – např. můžeme soubory označovat podle stupně utajení a aplikace je pak bude poskytovat jen uživatelům s příslušným pověřením. Možnostem využití se meze nekladou a záleží jen na vaší fantazii, co na téhle technologii postavíte.

Ukázková aplikace: rozsirene-atributy

Vytvořil jsem jednoduchou GUI aplikaci, která umožnňuje zobrazovat a měnit rozšířené atributy souborů. Stáhnout si ji můžete z mého mercurialu příkazem:

hg clone http://hg.frantovo.cz/rozsirene-atributy/

a potom přeložit pomocí antu. Jediné, co potřebujete je OpenJDK 7. Aplikace byla vyvinuta a testována s touto verzí:

java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b103)
Java HotSpot(TM) 64-Bit Server VM (build 19.0-b04, mixed mode)

Program se spouští takto:

rozšířené-atributy.sh název_souboru.txt

GUI programu Rozšířené atributy

Atributy můžete přidávat nebo mazat. Změny se provádějí hned, co ukončíte editaci příslušné buňky v tabulce.

Poznámka: protože se nejedná o žádnou kritickou aplikaci, rozhodl jsem se ji zneužít k jednomu experimentu. Podle Java Language Specification – 3.8 Identifiers se nemusíme omezovat jen na ASCII znaky, proto jsou všechny názvy tříd a metod v tomto programu psané česky a to včetně háčků a čárek.

„Letters and digits may be drawn from the entire Unicode character set, which supports most writing scripts in use in the world today, including the large sets for Chinese, Japanese, and Korean. This allows programmers to use identifiers in their programs that are written in their native languages.“

A vypadá to, že to skutečně funguje. Jestli chcete pomoci, otestujte program na své platformě a dejte vědět, jak to šlo.

Závěr

Dnešní článek měl dva cíle – jednak udělat osvětu rozšířeným atributům a jednak ukázat, jak snadno se s nimi pracuje (nebo bude pracovat) v nové verzi Javy. Odkazovaná GUI aplikace je svobodný software pod GNU GPL licencí. Je myšlena primárně jen jako ukázka nového API, ale třeba někomu bude k užitku. Zmínili jsme i standard pro metadata Dublin Core, který se vám může hodit nezávisle na souborových atributech – můžete ho využít třeba v XHTML.

Odkazy a zdroje

Online verze článku: http://www.linuxsoft.cz/article.php?id_article=1790