"Nu dori sa semeni numai graunte pentru propriul tau seceris; doreste sa semeni numai grauntele al carui fruct va hrani lumea." (Anonim)
p2j18jv
1. Scurt istoric
Foarte tinar, limbajul Java a fost proiectat, impreuna cu mediul
lui de dezvoltare si de executie, pentru dezvoltarea de aplicatii performante
destinate aparatelor electronice de larg consum (portabile, distribuite, lucrind
in timp real), ulterior influientind semnificativ Internetul. Firma
Sun, care s-a concentrat in proiectarea acestui nou limbaj, a pornit initial
la drum cu limbajul C, dar din cauza complexitatii ridicate a inceput sa dezvolte
un descendent mai flexibil, mai facil, mai portabil. Creatorul limbajului a
fost James Gostling, de asemeni autor al binecunoscutului program de editare
emacs din mediile UNIX si al sistemului de ferestre NeWS. Desi proiectul, denumit
initial Oak de la copacul din fata biroului parintelui sau, a debutat in
1990, specificatia noului limbaj s-a publicat abia in anul 1995 la conferinta
SunWorld din San Francisco. Descoperindu-se ca numele limbajului era deja utilizat,
Oak s-a transformat in Java, devenind deliciul programatorilor iubitori
de cafenele si de exotice arome. Din 1995 si pina in prezent, lumea
Java traieste intr-o continua agitatie, aparind alte si alte inovatii
si modificari ale limbajului, noi trasaturi si medii de dezvoltare, alaturi
de JDK (Java Development Kit) pus la dispozitie de compania Sun: Visual Java
(Microsoft), Visual Cafe for Java (Symantec), Visual Age for Java (IBM), SuperCede
for Java (Asymetrix) etc.
O parte din proiectantii de pagini Web au ramas reticienti la noul limbaj,
obiectind fie complexitatea suficient de ridicata, fie faptul ca nu oferea
toate facilitatile prezente in C++ din care se tragea. Astfel, Netscape
ofera un mediu orientat-obiect, inglobat in navigatorul propriu,
acest mediu fiind JavaScript, pe care il vom prezenta in urmatorul
capitol.
2. Caracterizare a limbajului
Trasaturile importante ale limbajului sint urmatoarele:
simplitatea
Java incearca sa ramina un limbaj usor de utilizat chiar si de catre
programatorii neprofesionisti, fiind indepartate aspecte derutante ca
supraincarcarea operatorilor si mostenirea multipla. De asemeni, lipseste
adresarea prin intermediul pointerilor.
portabilitatea
Limbajul Java este independent de masina pe care lucreaza (suport pentru portabilitate
si independenta hardware). In loc sa genereze cod nativ pentru o platforma
particulara, compilatorul va genera o secventa de instructiuni ale unei masini
virtuale Java (Java Virtual Machine - JVM), executia aplicatiilor fiind interpretata.
orientare-obiect
In Java se pot crea clase de obiecte si instante ale lor, se pot incapsula
informatiile, suportindu-se mostenirea simpla etc. Java insa nu
ofera mosteniri multiple, suplinite de o facilitate denumita interfata care
permite definirea unui anumit comportament pentru o clasa de obiecte, altul
decit cel specificat de clasa de baza.
distribuirea
Java este un limbaj distribuit, avind implementate biblioteci pentru lucrul
in retea (suport la nivel inalt pentru socket-uri si RMI - Remote
Method Invocation). Exista posibilitatea de a concepe aplicatii care lucreaza
cu mai multe fire de executie (thread-uri); exista desigur primitive de sincronizare,
independente de (ori bazate pe) sistemul de operare (Solaris, OS/2, Windows
NT ofera suporta pentru fire de executie multiple).
Setul de caractere al limbajului este Unicode (pe 16 biti), mai flexibil decit
setul ASCII (pe 8 biti). Aceasta facilitate ofera si posibilitatea de internationalizare
a codului.
Tipurile primitive sint urmatoarele:
Tip Valori Cuvint cheie boolean true, false boolean caracter cod Unicode char
intreg octet 8 biti byte scurt 16 biti short propriu-zis 32 biti int lung 64 biti long real flotant 32 biti float dublu 64 biti double
Tabelul 1. Tipurile primitive in limbajul Java
Tipurile referinta sint folosite pentru a referi un obiect din interiorul
altui obiect:
referinta catre o clasa referinta catre o interfata referinta catre un tablou
Desigur, operatorii sint similari celor din C si nu vom mai insista asupra
prezentarii lor. Exceptie fac operatorii de concatenare si asignare de siruri
care sint cei naturali (+ si =), in limbajul C/C++ fiind implementati
ca functii standard de biblioteca (strcat() si, respectiv, strcmp()).
Instructiuni blocuri de instructiuni delimitate intre A si S declaratii de variabile locale atribuirea instructiuni conditionale: if, switch instructiuni de ciclare: while, do, for instructiuni de salt: break, continue instructiuni de retur: return, throw instructiuni de protectie si de sincronizare: try, catch, finally, syncronized
Clase
Puterea limbajului Java rezida in faptul ca se ofera o serie de clase
predefinite, grupate, sau incapsulate, in pachete, din care utilizatorul
poate deriva propriile sale clase, mostenind cele de baza. Pachetele pot avea
nume ierarhice, urmind structura de directoare in care sint
stocate clasele compilate.
Astfel, in distributia Java 1.1.6, sint puse la dispozitie urmatoarele
pachete, continind peste 450 de clase si interfete:
java.applet java.awt.datatransfer java.awt.event java.awt java.awt.image java.beans java.io java.lang java.lang.reflect java.math java.net
java.rmi.dgc java.rmi java.rmi.registry java.rmi.server java.security.acl java.security java.security.interfaces java.sql java.text java.util java.util.zip
Tabelul 2. Pachetele de clase Java 1.1.6
3. Comparatie intre Java si C++
Vom prezenta o comparatie obiectiva intre limbajele Java si C++, insistind
mai ales pe aspectele fundamentale ale acestora.
Mostenirea multipla
In Java, mostenirea multipla (permisa in C++) a fost evitata prin
introducerea unei constructii noi denumite interfata, aproape identica cu o
clasa in C++, dar avind numai functii virtuale pure. Metodele declarate
intr-o interfata nu vor putea fi implementate in acea interfata.
O alta restrictie este ca o interfata nu poate detine membri de tip variabile.
Insa, programatorul va putea implementa oricite interfete doreste.
Managementul memoriei
Limbajul Java, spre deosebire de C++, utilizeaza mecanisme de colectare a memoriei
(garbage collection), pentru a elibera in mod automat blocurile de memorie
dupa ce toate referintele la ele au fost redirectate sau au disparut. Aceasta
facilitate duce la usurinta in programare, un dezvoltator de aplicatii
nu mai trebuie sa aiba in vedere si managementul memoriei, din moment
ce se realizeaza automat. O lipsa a limbajului Java este imposibilitatea de
accesare manuala prin program a memoriei, asa cum este posibil la C++.
Functia finalize
Functia finalize din Java corespunde conceptului de destructor din C++, fiind
apelata atunci cind un obiect este colectat in urma procesului de
garbage collection. Functia finalize dintr-o clasa derivata trebuie in
mod explicit sa apeleze functia finalize a clasei de baza:
class D extends B
A protected void finalize() throws Throwable
A super.finalize(); // finalizeaza B
// finalizeaza D
S
S
Conversii de tipuri prin toString
In cadrul unei clase se poate defini o metoda numita toString (vezi exemplul
de mai jos), ceea ce permite ca acea clasa sa poata fi utilizata oriunde in
cadrul programului trebuie specificat un obiect de tip sir de caractere:
class MyClass
A public String toString()
A return("MyClass as a String");
S
S
class Test
A public static void main(Stringai args)
A
MyClass obj = new MyClass();
System.out.println("I created a MyClass: " + obj);
i
S
Utilizind obj ca argument al operatorului de concatenare a sirurilor,
se invoca tacit metoda MyClass.toString(). Aceasta posibilitate de conversie
automata este o incercare, inca imatura, a conversiei automate de
tipuri (casting) realizata in limbajul C++.
Fire de executie (thread-uri)
Orice aplicatie ruleaza ca proces al sistemului de operare, fiecare proces detinind
un anumit numar de resurse alocate de catre sistem (fisiere deschise, memorie
alocata dinamic, fire de executie si altele).
Un fir de executie (thread) poate fi privit ca fiind o unitate de executie
a unui anumit proces. Fiecare fir de executie are asociate: o secventa de instructiuni,
un set de registri procesor si o stiva de memorie. Firele de executie proceseaza
instructiunile aplicatiei, fiecare dintre aceste fire putind rula in
paralel, pe un procesor separat (in cazul masinilor multi-procesor), ori
in maniera concurenta (pe calculatoarele mono-procesor).
La lansarea unei aplicatii Java, este creat automat un fir de executie central,
acesta putind ulterior (implicit sau explicit) sa creeze alte fire de
executie care la rindul lor pot genera alte fire de executie si asa mai
departe. Inafara de fire de executie cu prioritate normala, pot exista
fire de executie cu prioritate scazuta, rulind in fundal atunci
cind nici un alt fir nu poate fi rulat. Astfel de fire se numesc demoni,
executind de obicei operatii costisitoare in timp, independente
de celelalte fire de executie. Ca exemplu, se poate mentiona colectorul de gunoaie
(vezi mai sus) care lucreaza pe un fir de executie separat, cu proprietati de
demon. Sau, de pilda, se poate implementa un fir de executie demon pentru incarcarea
unui obiect multimedia (fisier film, voce etc.) de pe retea, necesitind
un timp indelungat de transfer.
Terminarea unei aplicatii Java are loc atunci cind se sfirsesc
toate firele sale de executie sau cind nu mai exista decit fire
de tip demon. Finalizarea firului principal de executie nu implica terminarea
automata a aplicatiei.
Implementarea unui fir de executie poate fi realizata fie prin operatiunea
de derivare din clasa Thread a unei noi clase, fie prin implementarea interfetei
Runnable in cadrul unei clase a utilizatorului, lansarea facindu-se
prin apelul metodei start, iar terminarea prin metoda stop. Desigur, mai multe
fire de executie pot fi grupate in diverse grupuri, sincronizarea lor
fiind realizata prin intermediul constructiei synchronized.
Template-uri
La fel ca si supra-incarcarea operatorilor, template-urile in Java
nu exista, spre deosebire de C++. Aceasta conduce la faptul ca oricare din conversiile
de tip permise sa fie sigure, un rezultat incorect ducind imediat la o
exceptie. Totusi, template-urile se folosesc foarte des pentru a obtine polimorfismul
static al obiectelor, ceea ce nu se poate, inca, in Java.
Instructiuni break si continue cu etichete
Desi ar putea parea un fapt minor, in Java este permisa specificarea de
etichete pentru o instructiune break sau continue, dar nu a fost introdusa intructiunea
goto:
outer: for (int i = 0; i < 99; i++)
A for (int j = 0; j < 99; j++)
A if (RightValue(i, j) == true) break outer; else
Compute(i, j);
S
...
S
Pentru a putea iesi din cele doua cicluri for imbricate, s-a folosit break.
Utilizarea lui break si continue in C, C++, Java, Delphi constituie o
violare minora a paradigmei un unic punct de intrare, un unic punct de iesire:
Fiecare bloc de cod sursa trebuie sa aiba un singur punct de intrare si un
singur punct de iesire din acesta, fiind interzisa intrarea ori iesirea in
mijlocul blocului. Intrarea se realizeaza intotdeauna la inceputul
blocului, iar iesirea la sfirsitul lui.
Aceasta conduce la aparitia de erori greu de identificat.
O solutie mai buna (folosind constructia try-finally) ar fi urmatoarea:
outer: for (int i = 0; i < 99; i++)
A try
A for (int j = 0; j < 99; j++)
A if (RightValue(i, j) == true) break outer; else
Compute(i, j);
S
S finally
A
...
S
S
O alta posibilitate este codul de mai jos, in clasicul stil C:
for (int i = 0; i < 99; i++)
A for (int j = 0; j < 99 && RightValue(i, j) == false; j++)
A
Compute(i, j);
S
...
S
4. Applet-uri Java
Applet-urile Java sint mici aplicatii Java ce ruleaza intr-un document
HTML, fiind incarcate in momentul accesarii paginii Web de pe server
si executate (interpretate) pe masina clientului. Fiecare applet are rezervata
o fereastra prin care comunica cu utilizatorul, definita de marcatorul <applet>.
import java.awt.Graphics;
public class HelloWorldApplet extends java.applet.Applet
A // mostenitor private String str; public void init() // metoda de initializare
A str = getParameter("msg");// memoreaza parametrul if (str == null) A // daca nu exista, se ia unul implicit str = "Hello, world!";
S resize(150, 100); // aloca zona de desenare
S
public void paint(Graphics gr) // scrie un sir de caractere
A // la coordonatele specificate gr.drawString(str, 50, 50);
S
S
Pentru a vedea efectiv rezultatele rularii applet-ului, scriem o pagina minimala
care va apela applet-ul de mai sus:
<html>
<head>
<title>Hello world!</title>
</head>
<body>
<p>Un mesaj:
<applet code="HelloWorldApplet.class" width=150 height=150>
</applet>
</body>
</html>
Applet-ul definit mai sus poate accepta si parametri (sirul de afisat) care
trebuie specificati de tag-ul <param>. De exemplu, in loc de "Hello,
world!" putem specifica "Hello, Faculty of Computer Science!"
incluzind dupa <applet> si:
<param name="msg" value="Hello, Faculty of Computer Science!">
Executia unui applet este marcata de o serie de evenimente generate de catre
navigator. Cind acesta intilneste <applet>, va porni
incarcarea (folosind tot protocolul HTTP) codului necesar rularii applet-ului,
cod aflat pe server si care va fi executat pe calculatorul client, odata ce
a fost incarcat complet. Dupa incarcare, applet-ul este apelat pentru
initializare (pregatirea parametrilor si obtinerea de resurse sistem). Dupa
aceasta etapa, navigatorul trimite catre applet o comanda de pornire si applet-ul
intrat in functiune va interactiona cu utilizatorul.
Figura 1. Interactiunea clasica server-client Web si interactiunea prin intermediul unui applet
incarcat de pe serverul java.sun.com
Un applet ruleaza atita vreme cit navigatorul este activ. La schimbarea
paginii, applet-urile din vechea pagina nu dispar, ci primesc o comanda de suspendare
(pe care pot s-o ignore).
Avantajul folosirii applet-urilor rezida in posibilitatea de a crea pagini
Web dinamice sau care sa se modifice in functie de preferintele si interactiunea
utilizatorului, de a partaja diferite applet-uri utile la nivel mondial. Iata
un exemplu in care un applet, implementind functiile unui program de calcul
tabelar (spreadsheet) poate fi rulat de mai multe navigatoare, pe diverse platforme,
aflate la diverse adrese Internet:
Figura 2. Un applet folosit in mai multe pagini Web procesate de diverse navigatoare
5. Servlet-uri Java
Inainte de a prezenta servlet-urile, trebuie amintit mediul de utilitare
JavaServer Toolkit (JST), bazat pe JDK, care ofera urmatoarele facilitati:
un cadru de lucru cu reteaua si cu firele de executie suportind protocoalele
UDP si TCP; administrare de la distanta prin Web; controlul accesului pe baza de identitati; suport pentru servlet-uri Java; suport pentru protocolul SSL (Secure Socket Layer) utilizat pentru autentificare
si confidentialitate; securitate a serverului pentru module incarcate dinamic de pe retea.
JST ofera pachete pentru:
infrastructura serviciilor: se ofera implementari ale algoritmilor multi-fire
de executie si de management al conexiunii;
administrare bazata pe Web: se ofera o serie de clase applet care faciliteaza
generarea de interfete standard de administrare a serviciilor (applet-urile
vor fi incarcate folosind HTTP si utilizeaza protocolul POST pentru a
contacta servlet-uri ce manipuleaza entitatile reale aflate pe server);
functionalitate a protocolului de transfer hipertext HTTP: sint suportate
specificatiile HTTP/1.0 care pot fi extinse folosind servlet-uri;
compilarea paginilor Web: posibilitatea de includere de cod Java in paginile
HTML statice si apoi sa se compileze aceste pagini, rezultind servlet-uri
Java pentru a crea un continut multimedia dinamic;
servlet-uri
utilitare: sint oferite unelte pentru urmarirea cererilor si a erorilor,
pentru managementul memoriei, pentru generarea de alarme etc.
Daca applet-urile erau aplicatii Java incarcate in cadrul paginilor
Web, rulind pe calculatorul client, servlet-urile se vor executa pe server,
reprezentind o solutie de rezolvare a problemelor de comunicare in
retea pe partea de server. Servlet-urile pot fi privite ca obiecte conformindu-se
unei interfete standard, instalate pe un server bazat pe Java.
Ca exemplu de utilizare se poate mentiona generarea de documente HTML dinamice.
Avantajele folosirii servlet-urilor sint urmatoarele:
sint mai rapide si mai sigure decit script-urile CGI; folosesc o interfata de programare standardizata (Servlet API); mostenesc avantajele limbajului Java (e.g. portabilitatea); se pot usor configura prin intermediul utilitarelor JST; pot fi inlantuite (un servlet poate apela unul sau mai multe servlet-uri,
in mod secvential); sint apelate dinamic din cadrul paginilor Web prin folosirea unor etichete
speciale.
Biblioteca de dezvoltare a aplicatiilor JavaServer asigura independenta de protocol,
poate fi extinsa (mostenindu-se functionalitatea claselor de baza care pot fi
dezvoltate ulterior de programatori) si este simpla. De asemeni, exista posibilitatea
de a fi utilizate o serie de servlet-uri interne (predefinite), cum ar fi: SSInclude
Servlet, File Servlet, Inkover Servlet, Admin Servlet, Cgi Servlet, Imagemap
Servlet.
Figura 3. Componentele interfetei de programare a serverului Java
Atit applet-urile, cit si servlet-urile isi gasesc multe utilizari
la ora actuala. Drept exemplu putem da realizarea de adnotari text, audio si
grafice pe marginea unor cursuri electronice. Astfel, se pun bazele invatamintului
virtual la distanta, prin intermediul WWW, folosind tehnici hipermedia sofisticate:
Figura 4. Utilizarea applet-urilor si servlet-urilor Java pentru adnotarea cursurilor disponibile pe Web
O aplicatie complementara sistemului prezentat in figura de mai sus (implementat
la Universitatea Hagen din Germania) este Dynamic Courseware Generator (DCG),
o colectie de unelte software generind in mod automat de cursuri
disponibile pe Web, folosind tehnologia Java, varianta de test functionind
pentru cursul de Computer Based Learning Systems:
Figura 5. Interfata DCG cu utilizatorul
6. Comunicatii TCP/IP
Limbajul Java, prin biblioteca de clase java.net, furnizeaza o interfata de
nivel inalt pentru scrierea de aplicatii Internet bazate pe protocolul
TCP/IP.
6.1 Scrierea de aplicatii TCP in limbajul Java
In pachetul java.net exista mai multe clase pentru manipularea socket-urilor.
Socket-urile sunt utile in Java pentru implementarea fluxului de comunicatie
intre programe. Ele reprezinta principala modalitate de comunicare in
Internet, respectind modelul client-server. Paginile Web, transferul de
fisiere si posta electronica rezolva problemele de comunicatie prin intermediul
socket-urilor. Datorita interfetei Java pentru socket-uri, pot fi create cu
usurinta aplicatii care sa participe la conectivitatea retelei.
Java foloseste pentru socket-uri trei clase din pachetul java.net: ServerSocket,
Socket si SocketImpl. Primele doua sint utilizate, in general, de
catre programatori. Ultima clasa, SocketImpl, este de obicei implementata de
sistemele de operare care recunosc limbajul Java.
Clasa ServerSocket
ServerSocket reprezinta socketul creat pentru server. Clasa ServerSocket asteapta
o cerere de conectare din partea unui client si accepta conectarea la un port
al serverului.
Dintre metodele clasei, cele mai importante sint accept() si close().
Metoda accept() (blocanta) este folosita pentru crearea unui socket si atasarea
acestuia la un port al serverului. Metoda close() intrerupe o conexiune
care si-a incheiat activitatea.
Odata ce clientul realizeaza un socket de conexiune, ServerSocket returneaza
(prin metoda accept()) partea socket-ului corespondenta serverului prin care
va avea loc comunicatia directa. Acum avem o conexiune reala Socket la Socket
(peer-to-peer) si vom trata ambele capete ale conexiunii in acelasi mod.
Din acest punct se pot folosi metodele getInputStream() si getOutPutstream()
pentru a citi, respectiv scrie, obiecte corespondente InputStream si OutputStream
pentru fiecare socket in parte (privite ca obiecte de tip flux de date).
Clasa Socket
Clasa Socket este raspunzatoare pentru realizarea conexiunilor si proceselor
de retea. Ea este folosita impreuna cu clasa SocketImpl, pentru implementarea
operatiilor efective cu socket-uri. Cele doua clase sint separate, astfel
incit implementarea operatiilor cu socket-uri poate fi modificata
in functie de sistemul de protectie folosit.
6.2 Servere concurente
Scrierea de serverele concurente in Java se bazeaza pe facilitatea intrinseca
a limbajului: multi-threading-ul (posibilitatea de a lansa mai multe fire de
executie independente, fiecare din ele deservind cererile provenite de la un
anumit client).
6.3 Aplicatii UDP in Java. Datagrame
Dupa cum am mentionat ulterior in cadrul acestei lucrari, datagramele
reprezinta date trimise prin intermediul unui pachet independent. Fiecare pachet
este transmis de la o masina la alta doar pe baza informatiilor continute de
el insusi. Pachete trimise de la o destinatie catre aceeasi sursa pot
ajunge pe rute diferite si in orice ordine (nu se garanteaza siguranta
transportului).
Diferenta fata de comunicarea printr-un canal sigur oferita de metoda comunicatiei
prin conexiuni (socket-uri) este ca, folosind datagrame, nu se stabileste o
legatura permanenta intre client si server. O datagrama este implementata
de clasa DatagramSocket.
Informatiile incapsulate in cadrul unei datagrame (adresa de destinatie,
portul de expediere, continutul propriu-zis) sint, in Java, continute
de obiecte de tip DatagramPacket, metodele cele mai folosite fiind: getAddress(),
setAddress(), getPort() si setPort().
7. Dezvoltarea aplicatiilor Java
In cadrul mediului de dezvoltare a aplicatiilor Java JDK (Java Development
Kit), firma Sun ofera o serie de unelte software utile, dintre care mentionam:
javac
Compilator Java pentru a genera cod binar Java. java
Interpretor Java pentru a rula codul binar produs de javac. jre
Interpretor Java folosit de utilizatorii finali pentru executia programelor
Java (mai simplu decit aplicatia java). jdb
Depanator simbolic Java, foarte asemanator cu depanatorul standard dbx din mediile
UNIX. javadoc
Generator de documentatie HTML pentru codul sursa Java. appletviewer
Vizualizator de applet-uri, fara a necesita prezenta unui navigator Web. native2ascii
Convertor de fisiere scrise in cod non-Unicode Latin-1 in fisiere
Unicode Latin-1. jar
Arhivator de fisiere .class, imagini si sunet intr-o singura arhiva Java
(JAR) pentru a micsora timpul de transfer (se asigura astfel o unica tranzactie
HTTP pentru a aduce de pe retea toate fisierele necesare rularii applet-urilor).
8. Prezent si viitor
In ciuda tineretii sale, limbajul Java a avut, are si va avea o dezvoltare
incredibila, in special in partea aplicatiilor Web.
JavaOS - un sistem de operare compact, proiectat pentru a rula programe Java
direct pe microprocesoarele oricarui echipament electronic: calculator de retea,
imprimanta, automat pentru jocuri, telefon celular etc., interfata de programare
JDBC (Java DataBase Connectivity) destinata conectarii la baze de date prin
Java permitind unei aplicatii client sa acceseze direct sistemul de gestiune
a unei baze de date, executind instructiuni SQL, mii de applet-uri disponibile
(emulatoare de terminale TELNET, jocuri interactive, animatii, programe de tele-conferinte
si altele), XP (James Clark's XML Parser) - un analizator lexical XML, JavaCC
(Java Compiler-Compiler) - generator de analizatoare lexicale orientat-obiect,
pentru limbajul Java, toate acestea si multe altele sint marturii ca lumea
programatorilor in Java este in plina efervescenta si ca in
viitor vom asista, speram, la o maturizare si stabilizare in specificatiile
limbajului.
9. Referinte bibliografice
I.Athanasiu et al. - "Limbajul Java - O perspectiva pragmatica", Ed.Libris,
1998
K.Arnold, J.Gosling - "The Java Programming Language", Addison-Wesley,
1996
J.Clark - "XP - An XML Parser in Java": https://www.jclark.com/xml/xp
S.A.Cristescu - "Java Web Server", PC Report, vol.7/10, nr.73, oct.1998
J.Fink , A.Kobsa , J.Schreck - "Personalized Hypermedia Information Provision
through Adaptive and Adaptable System Features: User Modeling, Privacy and Security
Issues", Sixth International Conference on User Modeling, Chia Laguna,
jun.1997
R.Martin - "Java and C++, A Critical Comparation", Java Journal, March
1997
K.Moss - "Java Servlets", McGraw-Hill Press, 1998
F.Neil, R.Terry - "Java - A Practical Guide", Oxford, 1997
P.Norton - "Ghid de programare in Java", Editura Teora, Bucuresti,
1998
M.Pesce - "VRML and Java", ViewSource, Netscape Communications, 1999
C.Rodrigues - "Calling Native Methods from Server-Side Java", View
Source, Netscape Communications, apr.1998
E.Rotariu - "Limbajul Java", Computer Agora Press, Tg.Mures, 1996
S.Shirmohammadi, J.de Oliveira, N.Georganas - "Applet-Based Multimedia
Telecollaboration: A Network-Centric Approach", Univ. of Ottawa, 1997
C.Unger - "The University of Hagen in Transition to a Virtual University",
Iasi, jul.1999
J.Vassileva - "Dynamic Course Generation on the WWW", Federal Armed
Forces University Munich, Neubiberg, 1996
M.White - "Designing Dynamic Hypertext", HYPERTEXT'98 Proceedings,
Pittsburgh, jun.1998
* * * - "JavaTM Development Kit Documentation", Sun Microsystems Inc.,
Palo Alto, 1999: https://java.sun.com/products/jdk/
* * * - "JavaCC": https://www.suntest.com/JavaCC
* * * - "JavaSoft Home Page": https://java.sun.com