Formatul JAR (Java Archive) permite impachetarea mai multor fisiere intr-o singura arhiva. Un fisier JAR va contine in mod tipic fisiere .class si alte fisiere auxiliare (de exemplu imagini, fisiere audio etc.).
Formatul JAR a fost introdus de catre SUN incepand cu versiunea 1.1 a JDK (Java Development Kit). O data cu versiunea 1.2, si formatul JAR a cunoscut unele imbunatatiri.
Iata cateva dintre caracteristicile fisierelor JAR:
- Securitate. Continutul unui fisier JAR poate fi semnat digital, astfel incat numai persoanele care recunosc semnatura pot beneficia de privilegiile de securitate. Voi reveni pe parcursul articolului.
- Scaderea timpului de download. Daca toate fisierele unui aplet (inclusiv auxiliare) sunt adunate intr-un singur fisier, atunci acesta poate fi descarcat de catre browser intr-o singura transactie HTTP (se stie ca pentru fiecare nou fisier pe care browserul trebuie sa-l aduca de pe server, se realizeaza o noua conexiune TCP).
- Compresie. Formatul JAR permite comprimarea fisierelor (cu formatul ZIP).
- “Sigilarea” pachetelor (numai versiunea 1.2). Pachetele dintr-un fisier JAR pot fi “sigilate”. Acest lucru inseamna ca toate fisierele definite in pachetul respectiv trebuie sa se gaseasca in acelasi fisier JAR pentru ca toate sa fie interpretate cu aceeasi versiune de Java.
- Informatii privind vesriunea pachetului. Un fisier JAR poate pastra date despre fisierele pe care le contine, de exemplu versiunea, producatorul, etc.
- Portabilitate. Aceasta caracteristica se aplica limbajului Java in general, cu tot ce este legat de el, prin urmare si mecanismul acesta de arhivare este o parte standard a platformei Java API.
Dupa aceasta introducere, vom vedea in continuare cum se creeaza si cum se folosesc fisierele JAR si alte fisiere importante continute in JAR (fisierul manifest). Apoi voi prezenta cateva elemente legate de semnarea si autentificarea fisierelor JAR.
Fisierele JAR sunt arhive de tip ZIP. Deci ele pastreaza caracteristicile formatului ZIP, si anume: compresia datelor fara pierdere de informatii, arhivare, decompresie.
Pentru a realiza sarcinile unui fisier JAR trebuie sa folosim unealta furnizata ca parte a JDK: Java Archive Tool. De fapt aceasta unealta este folosita prin comanda jar si vom vedea in continuare cum o vom folosi.
Nota: Indiferent de mediul de dezvoltare Java pe care il folositi (Symantec Visual Cafe, Borland JBuilder, Oracle JDeveloper sau oricare altul), acesta are ca motor de compilare si interpretare pachetul JDK de la Sun. Aceste medii ofera in plus interfete prietenoase menite sa ajute programatorul, eventual ofera in plus o suma de alte clase care pot fi folosite, ofera unelte vizuale. Dar toate acestea folosesc de fapt uneltele standard oferite de Sun. Ele se afla de obicei in directorul java/bin, aflat in directorul home al programului respectiv instalat.
Revenind la tema articolului de fata, desigur ca toate aceste medii de dezvoltare java au optiuni de creare a fisierelor JAR. Dar acestea apeleaza de fapt utilitarul jar din JDK. De aceea voi prezenta aici modul de folosire a acestui utilitar.
Formatul de baza pentru crearea unui fisier JAR este urmatorul : jar cf fisier_jar fisiere_input Optiunile si argumentele care pot fi folosite in aceasta comanda sunt :
- c = create – creeaza un fisier JAR;
- f = file – indica faptul ca output-ul comenzii se va duce intr-un fisier, si nu la stdout, mai precis in fisierul fisier_jar ;
- fisier_jar – numele fisierului jar care va resulta si care va avea numele fisier_jar.jar ;
- fisiere_input – este o lista de fisiere care vor fi plasate in fisierul .jar. Lista va fi separata prin spatii. Simbolul * poate fi folosit pentru a indica un sablon de mai multe fisiere. Daca unul dintre fisierele-input este nume de director, atunci toate fisierele continute in acest director vor fi adaugate arhivei.
Comanda de mai sus va genera un fisier. jar comprimat si il va plasa in directorul curent. Comanda va genera si un fisier manifest, despre care voi vorbi mai tarziu in acest articol. Urmatoarele optiuni mai pot fi adaugate comenzii de creare a unui fisier .jar :
- v = verbose – afiseaza pe ecran informatii referitoare la fisierele adaugate (numele, rata de comprimare etc) pe masura ce fisierul JAR este construit.
- 0 = zero – se foloseste in cazul in care nu se doreste ca fisierul .jar sa fie comprimat. De exemplu un fisier necomprimat va mari viteza de executie a fisierelor continute in arhiva pentru ca decomprimarea lor nu mai este necesara (operatie consumatoare de timp). Bineinteles ca timpul de download va fi mai mare in acest caz, pentru ca dimensiunea fiiserului .jar va fi mai mare. Dar de exemplu in cazul folosirii unui fisier .jar in Intranet, unde timpul suplimentar de download nu este semnificativ mai mare, aceasta optiune poate fi o solutie buna pentru cresterea vitezei de executie.
- -C = change directory (numai versiunea 1.2) – schimba directorul in timpul executiei comenzii. Astfel, structura de directoare nu mai este pastrata, toate fisierele fiind plasate pe primul nivel, fara nici o structura de directoare.
Comanda urmatoare :
jar cvf joc.jar joc.class img
creeaza fisierul joc.jar din clasa joc.class si toate fisierele continute in directorul img. Comanda afiseaza informatii pe ecran pe parcursul crearii fisierului, si anume ceva de genul:
adding:joc.class (in=2145) (out=1755) (deflated 36%) adding:img/ (in=0) (out=0) (stored 0%) adding:img/sfera.gif (in=648) (out=632) (deflated 2%) adding:img/bila.gif (in=314) (out=310) (deflated 1%)
Vizualizarea continutului unui fisier JAR
Comanda pentru vizualizarea continutului unei arhive .jar este urmatoarea:
jar tf fisier_jar
unde t = table of contents – indica faptul ca se vrea vizualizarea tabelei de continut (continutului) a arhivei fisier_jar. Optiunea v (verbose) poate fi adaugata si aici. De exemplu dupa crearea arhivei joc.jar, comanda:
jar tf joc.jar afiseaza: META-INF/MANIFEST.MF joc.class img/ img/sfera.gif img/bila.gif
Fisierul JAR contine deci cele 3 fisiere plus directorul img/, si mai contine in plus fisierul manifest, care a fost automat plasat aici de catre utilitarul jar.
Adaugarea ulterioara a unor fisiere suplimentare in arhiva se face cu ajutorul comenzii:
jar uf fisier_jar fisiere_input - u = update;
Comanda:
jar uf joc.jar joc.class img/bila2.gif
adauga imaginea /bila2.gif si suprascrie in arhiva fisierul joc.class.
Extragerea continutului unui fisier JAR
Comanda utlizata pentru a extrage continutul unui fisier arhiva .jar este urmatoarea:
jar xf fisier_jar [fisiere_arhivate]
- x = extract;
- argumentul optional fisiere_arhivate indica fisierele de extras. Daca el nu este prezent, toate fisierele din arhiva vor fi extrase.
Exemplu:
jar xf exemplu.jar exemplu.class img/imagine.gif
extrage din arhiva numai fisierele specificate, realizand o copie a lor in directorul curent.
Fisierul manifest este un fisier special care contine informatii referitoare la fisierele impachetate in arhiva .jar. Modul de construire a acestui fisier are implicatii directe asupra scopului pe care fisierul JAR trebuie sa-l indeplineasca.
Cand este creat un fisier .jar, acesta va primi un fisier manifest implicit. O arhiva .jar poate contine un singur fisier manifest, care se afla in directorul META-INF si are numele MANIFEST.MF.
O intrare in fisierul manifest are forma: “nume: valoare”
Daca fisierul JAR este creat cu versiunea JDK 1.2, atunci fisierul manifest implicit are o singura linie:
Manifest-Version: 1.0
In functie de rolul pe care doriti ca fisierul JAR sa-l joace, veti avea nevoie sa modificati fisierul manifest sau nu. De exemplu daca sunteti interesat numai de caracteristicile ZIP ale fisierului JAR (adica arhivare si compresie), continutul fisierului manifest nici nu va intereseaza. Iata mai jos cateva situatii in care trebuie sa modificati continutul fisierului manifest:
Aplicatii impachetate in fisierul JAR (numai versiunea 1.2)
Daca fisierele impachetate in fisierul JAR constituie o aplicatie, atunci in fisierul manifest se poate specifica numele clasei de pornire a aplicatiei ( adica a clasei care contine functia: public static void main (String args)). Aceasta informatie se poate specifica cu ajutorul header-ului Main-Class, astfel:
- Main-Class: classname
Extensii de download (numai versiunea 1.2)
Extensiile de download sunt fisiere JAR referite de catre fisierele manifest ale altor fisiere JAR. Astfel, un aplet va fi impachetat intr-un fisier .jar. Manifestul acestuia face referinta la unul sau mai multe alte fisiere .jar care vor servi ca extensii ale apletului initial. Extensiile se pot referi unele pe altele in acelasi fel.
Extensiile de download sunt specificate folosind header-ul Class-Path, de exemplu:
Class-Path: salvari.jar alte/optiuni.jar
Clasele din fisierele salvari.jar si alte/optiuni.jar sunt extensii pentru apletul sau aplicatia care contine acest fisier manifest.
Sigilarea Pachetului (numai versiunea 1.2)
Un pachet arhivat intr-un fisier .jar poate fi sigilat. Acest lucru inseamna ca toate clasele definite in acel pachet trebuie sa fie arhivate in acelasi fisier JAR. Acest lucru asigura consistenta versiunii folosite de clasele din pachet, si este de asemenea si o masura de securitate.
Pentru a sigila un pachet, urmatoarele linii trebuiesc adaugate fisierului manifest:
Name: nume_pachet/ Sealed: true
Versiunea pachetului (numai versiunea 1.2)
Pentru a specifica versiunea pachetului arhivat, exista mai multe headere. Un set de astfel de headere poate fi asignat fiecarui pachet din arhiva. Toate aceste headere trebuie scrise imediat dupa numele pachetului, fara nici o linie libera intre ele. Iata un exemplu:
Name: issa/usr Specification-Title: "Utilizatori" Specification-Version: "1.1" Specification-Vendor: "Netix SRL" Implementation-Title: "issa.usr" Implementation-Version: "issa12" Implementation-Vendor: "Netix SRL"
Modificarea fisierului manifest
Cum se adauga toate aceste optiuni prezentate mai sus intr-un fisier manifest? Optiunea “m” a utilitarului Jar permite adaugarea de linii suplimentare in fisierul manifest, in momentul crearii sau modificarii arhivei. Liniile de adaugat se scriu intr-un fisier de tip ASCII, sa-l numim adaugare_manifest.txt.
Comanda:
jar cmf adaugare_manifest.txt fisier_jar fisiere_input
creeaza arhiva fisier_jar.jar. Fisierul sau manifest va contine fisierul adaugare_manifest.txt.
O comanda asemanatoare se poate folosi in cazul in care fisierul .jar exista deja si se doreste modificarea acestuia. Diferenta este ca in loc de optiunea c (create), trebuie folosita optiunea u (update).
Rularea apleturilor sau aplicatiilor impachetate intr-un fisier JAR
Un aplet impachetat intr-un fisier .jar poate fi apelat din fisierul parinte .html astfel:
<applet code=”exemplu.class” archive=”../../Downloads/News/er/joc.jar” width=”200″ height=”150″></applet>
O aplicatie poate fi rulata folosind JDK 1.1 astfel:
jre -cp arhiva.jar clasa_principala
In versiunea 1.2, comanda:
java -jar arhiva.jar
executa aplicatia pornind de la clasa specificata in fisierul manifest sub header-ul Main-Class. Optiunea -jar spune interpretorului java ca aplicatia este arhivata sub formatul JAR.
Semnarea si verificarea fisierelor JAR
Un fisier JAR poate fi semnat cu o semnatura electronica. Motivul semnaturii este acelasi cu motivul semnarii unui document scris pe hartie : si anume pentru ca cititorii, care bineinteles recunosc semnatura, sa fie asigurati ca dumneavoastra sunteti acela care a scris documentul, sau cel putin are aprobarea dumneavoastra. Procesul de recunoastere a semnaturii se numeste verificare.
Prin recunoasterea unui aplet semnat, clientul are posibilitatea sa treaca peste privilegiile de securitate (de exemplu sa scrie pe discul local). Astfel, un aplet de incredere (trusted) va avea aceeasi libertate sa execute operatii ca si cum ar fi de fapt o aplicatie rulata local.
Semnarea si verificarea in Java se face prin folosirea unor chei speciale : si anume a unei chei private si a uneia publice, care sunt complementare.
Cheia privata este ‘stiloul electronic’ si este cunoscuta numai de catre persoana care face semnatura. Un fisier semnat cu o cheie privata poate fi verificat numai cu ajutorul cheii publice corespunzatoare.
Pentru a putea semna insa documentele, este nevoie de un certificat. Acesta trebuie cumparat de la o autoritate recunoscuta, care indica cine este detinatorul cheii publice continute in arhiva JAR. O autoritate de unde se poate cumpara un astfel de certificat este VeriSign. Puteti citi mai multe informatii de pe pagina www.verisign.com.
Atunci cand semnati un fisier JAR, cheia publica este plasata in interiorul arhivei, impreuna cu certificatul, disponibil oricui doreste sa verifice semnatura.
Deci semnatura digitala se face astfel : autorul semneaza fisierul JAR folosind cheia sa privata. Cheia publica corespunzatoare se va afla in arhiva, impreuna cu certificatul, si vor fi disponibile oricui doreste sa le verifice.
La semnarea fisierului JAR, un fisier este automat generat si plasat in directorul META-INF, acelasi cu directorul fiserului manifest. Fisierele de tip semnatura au extensia .SF (signature file) si contin niste intrari digest (niste coduri) pentru fiecare fisier continut in arhiva. Aceleasi intrari digest se gasesc si in fisierul manifest.
Exemplu:
Name: issa/usr/utilizator.class SHA1-Digest : bHSKHgdshdscs2hu67=
Atunci cand fisierul JAR este verificat, codul fiecarui fisier este recalculat si comparat cu cel din fisierul manifest, pentru a asigura faptul ca arhiva nu a fost schimbata de cand a fost semnata.
Ca unealta pentru semnarea si verificarea arhivelor, JDK 1.2 ofera utilitarul jarsigner :
jarsigner fisier_jar alias
unde alias reprezinta fisierul unde se afla cheia privata cu care se va semna.
Verificarea unei arhive semnate se face astfel :
jarsigner -verify fisier_jar
Daca verificarea se incheie cu succes, va da mesajul:
jar verified
Daca nu, va da mesajul :
jar is unsigned. (signature missing or not parsable)