Valhalla.fr

Sic Itur Ad Absurdum

"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
30 Août 2001

Article de Sun traduit et adapté en français.

Qu’est-ce que Java IDL ?

Java IDL est une technologie pour les "objets distribués", c’est-à-dire des objets interagissant avec différentes stations de travail d’un réseau. Java IDL est similaire à RMI (Remote Method Invocation) qui supporte des objets distribués écrits entièrement et exclusivement en langage Java. Cependant, Java IDL permet aux objets d’être utilisés même s’ils sont écrits dans un langage différent de Java, comme C/C++, Cobol, et bien d’autres.

Ceci est possible car Java IDL est basé sur l’architecture CORBA (Common Object Request Brokerage Architecture), un standard mondial de l’industrie dans la distribution d’objets sur un réseau. Une des composantes de Corba est IDL (Interface Definition Language), langage dit "neutre". Chaque langage de programmation supportant Corba implémente une IDL, d’où le nom de "Java IDL", l’implémentation IDL pour Java. Corba et IDL sont issus d’un consortium de trusts mondiaux (notamment IBM, Boeing, etc.) connus sous le nom de OMG (Object Management Group), et le fait que Sun Microsystems soit l’un des membres fondateurs explique que IDL soit si bien adapté à Java.

Pour permettre des interactions entre les objets de différents programmes d’un réseau, Java IDL "fourni" un ORB (Object Request Broker). Un ORB est une bibliothèque de classes qui permet une communication de bas niveau entre Java IDL et d’autres applications basées sur Corba.

L’architecture CORBA

Une interaction entre 2 objets sur un réseau a toujours 2 sens: le client et le serveur (entrée/sortie su vous préférez). Le serveur crée une "Remote Interface" (c’est à dire une porte d’entrée vers lui), et le client appelle et utilise cette "Remote Interface". Ceci est globalement la procédure généralisée utilisée par les standards d’objets distribués comme RMI ou Corba. On notera que les mots "client" et "serveur" désignent des interactions au niveau des objets et pas des applications: un logiciel peut être à la fois client et serveur selon s’il publie ou reçoit tel ou tel objet.

Du côté du client, l’application a une référence vers l’objet distribué. La référence a une méthode "stub" ("stub" signifie le "talon" d’un ticket en anglais) qui est une sorte des remplaçant pour la méthode appelée à distance. Le "stub" est installé dans l’ORB, l’appeler revient donc à activer les fonctions de communication de l’ORB qui se chargera de la connexion au serveur.

Du côté du serveur, l’ORB utilise un "squelette" de code pour traduire l’appel à distance en un appel de méthode sur un objet local. Le squelette se charge de bien traduire la requête dans le format attendu par l’objet local. Quand la méthode finit (à comprendre: quand elle retourne) le squelette se charge de traduire la valeur de retour ou les erreurs et de les transmettre à l’ORB qui les transmet à son tour au client.
Entre les ORB, la communication est établie grâce à un protocole spécial: IIOP (Internet Inter-ORB Protocol). IIOP, basé sur le standard TCP/IP, définit comment des ORB pour Corba échangent des informations. Tout comme Corba et IDL, IIOP est un standard définit par l’OMG (Object Management Group).

En plus des possibilités de communication exposées plus haut, les ORB basés sur Corba ont des fonctionnalités améliorées, des services définis par l’OMG. Ceci inclut la recherche d’objets par nom, la persistance d’objets, la possibilité d’échanger des messages, etc. Certains ORB supportent ces fonctions, celui fourni avec Java IDL supporte la recherche d’objets par nom.

Le processus de développement de Java IDL

1) Définir l’interface à distance
On définit l’interface à distance en utilisant le langage de définition de l’interface de l’OMG, c’est à dire IDL. On utilise IDL plutôt que Java car le compilateur idl-to-java travaille à partir d’un (code) source IDL, générant tous les fichiers "stub" et "squelette" avec le code d’infrastructure nécessaire à la connexion avec l’ORB. En utilisant IDL, on permet aux autres développeurs d’implémenter des clients et des serveurs dans d’autres langages compatibles Corba.

2) Compiler l’interface à distance
Quand on lance le compilateur idl-to-java sur le fichier source de définition de l’interface, il génère une version en Java de l’interface, comme il génère les stubs et les squelettes.

3) Implémenter le serveur
Une fois le compilateur idl-to-java lancé, on peut utiliser les squelettes générés pour assembler son serveur. En plus d’implémenter les méthode de l’interface à distance, le code du serveur inclut un mécanisme pour lancer l’ORB et attendre une requête d’un client.

4) Implémenter un client
De même on utilisera les stubs générés par le compilateur comme base pour l’application client. Le code client construit à partir des stubs lance l’ORB de son côté qui recherche une connexion vers le serveur utilisant le service de noms indiqué par Java IDL, obtient une référence vers l’objet à distance et invoque à distance ses méthodes.

5) Démarrer l’application
Une fois le serveur et le client créée, on peut lancer le service de noms, puis démarrer le serveur, et enfin lancer le client.

Notes:
1) Avec Java 1.3, idltojava compiler est remplacé par idlj compiler
2) Si vous désirez un exemple concret: HelloWorld! dans la suite de cet article de la FAQ. Article Sun ici.

Traduit et adapté de l’anglais par Narcanes, (article original de Jim Inscore Sun Microsystems)
pour l’association Java-France/Jgflsoft
www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Montpellier, 30 août 2001.

• 890 mots • #programmation #serveur #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
28 Août 2001

Traduction (adaptation, simplification) d’un article de Sun.

Historique

Comment sommes-nous arrivés à un stade où l’orientation "online" des services et du matériel informatique est la préoccupation majeure des fabriquants ?

L’explication la plus évidente est notre meilleure connaissance de domaines scientifiques tels que la chimie ou l’électronique appliqués à la micro-informatique. De nos jours, un ordinateur personnel peut être fabriqué à partir d’un minimum de matériel et les serveurs d’entreprise ne sont plus ces gros amas de tôles et de câbles occupant des pièces entières.

Dans les années 60, seules les grosses entreprises pouvaient se payer le luxe d’un ordinateur (d’un de ces amas de tôles et de câbles).

Puis vient la miniaturisation et la création de terminaux: des écrans et des claviers, sans grosse unité centrale, reliés en réseau à un serveur. Cela résolvait pas mal de problèmes de place, et annoncait le début de la vague "online".

Les "stations de travail", ordinateurs du format de ceux d’aujourd’hui, firent leur apparition un peu plus tard. Ils offraient une puissance suffisante pour les travaux scientifiques tels que le dessin technique, le développement d’application scientifiques…

L’ordinateur personnel (PC) était également assez petit pour tenir sous une table et assez puissant pour offrir des fonctionnalités telles qu’une interface graphique à ses utilisateurs.

De nos jours la miniaturisation en est à un tel point que les voitures ont en moyenne une cinquantaine de microprocesseurs, et que l’on peut en trouver plus d’une centaine dans une maison.

Mais la création de ces ordinateurs toujours plus petits et moins cher a eu une retombée imprévue: la disparition d’une forme de vie en communauté. En effet, les ordinateurs étant plus disponibles, il n’était plus nécessaire des les partager entre plusieurs personnes, tout le monde pouvait avoir son ordinateur personnel, au travail comme à la maison.
Et l’internet domestique pallie à cet effet: les stations de travail et les ordinateurs pesonnels ne sont vraiment utiles dés lors qu’ils sont connectés entre eux afin de pouvoir communiquer.

Plus loin dans cette voie, les ordinateurs peuvent maintenant échanger des objets (comprenez: des classes Java) et supporter des langages orientés objet et communication. Pout la plupart des gens un ordinateur sert avant tout à chercher des informations sur internet, communiquer par e-mail, etc…

Comment fonctionne Jini ?

La technologie Jini est une architecture pour la construction de systèmes à partir d’objets (de classes…) et de réseaux. La technologie Jini permet aux programmes d’utiliser des services dans un réseau sans savoir quoi que ce soit du protocole de connexion de ce réseau. Une implémentation d’un système pourrait être basée sur les RMI, une autre sur XML et encore une autre sur CORBA. Le client Jini interroge les services qui lui répondent comment ils s’utilisent ! Un service est défini par une API, déclarée comme une interface de programmation Java.

Quand un service est "branché" à un réseau ou matériel basé sur l’architecture Jini, il s’identifie en publiant un objet Java qui implémente l’API du service concerné.
Le client trouve des services en cherchant un objet supportant l’API Jini. Une fois connecté au service, il télécharge un code qui lui indique comment communiquer avec ce service. Les programmeurs qui auront implémenté le service auront choisi comment transformer une requête de l’API en bits de manière à utiliser un protocole comme UPnP, RMI, Corba ou un protocole privé.

Créer une communauté autour de la technologie Jini

Quand internet fur créé, les deux préoccupations majeures étaient de définir et de perfectionner les protocoles de communication et les infrastructures du réseau, et de créer des services et des applications utilisant ce réseau. L’infrastructure d’internet inclu les protocoles TCP/IP, HTTP, SMTP, FTP (etc…), et leurs implémentations. Avec ces protocoles furent créée des logiciels comme les navigateurs, les clients e-mail ou les clients FTP, et même le Web lui même. Ce n’est pas une seule entreprise aui réussit à créer Internet, mais de nombreuses entreprises ayant adopté les mêmes protocoles, ayant des standars. C’est pourquoi pour que Jini réussisse, un grand nombre de personnes doit l’utiliser. Plus il sera utilisé plus facilement il devientra une technologie de référence.

La Sun Community Source License (SCSL) a été crée pour mettre en place une communauté autour de Jini. La SCSL donne libre accès au code source de la technologie Jini et de ses dévés, libres de droits en utilisation et modification.

Liens

Pour s’enregistrer http://www.sun.com/jini/licensing/
Des infos sur la communauté: http://www.sun.com/jini/community/

Traduit par Narcanes (narc[email protected])
à partir d’un article de Sun,
pour l’association Java-France / Jgflsoft
www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Montpellier, 28 août 2001.

• 771 mots • #programmation #serveur #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
3 Juill 2001

Ce chapitre de la FAQ a pour but de montrer comment exporter, sous la forme d’une archive JAR, un programme Java (application, applet, servlet, web app, bean, etc…). Nous utiliserons ici la situation la plus simple: une application (avec méthode main()) exportée dans une archive JAR auto-exécutable. Nous détaillerons les étapes de la création d’une telle archive.

NOTE 1: Pour des raisons de temps notamment (JBuilder 5 n’est pas encore sortie en France à l’heure de la rédaction de cet article), la version de JBuilder utilisée sera la version US.

NOTE 2: cette page contient de nombreuses images, le temps de chargement peut être assez long…

1) Lancer l’outil, ou wizard, d’exportation: Menu WIZARDS -> ARCHIVE BUILDER

JarExport

2) Première étape de l’exportation: le choix d’un format.

JarExport

Nous choisissons ici le format "Application". On peut cependant prendre "Basic" (comme "Application" mais non auto-exécutable), Applet pour exporter des applets, Web Start pour exporter des Web App, etc… Une description de chaque option est faite dans la case de la fenêtre "Description".

3) Résolution des dépendances (1)

Un programme Java a la plupart du temps des dépendances, c’est à dire des classes ou des packages absolument nécessaires pour s’exécuter. Par exemple, un programme utilisant une interface graphique Swing devra absolument intégrer les classes du package Swing nécessaires. Pas besoin de spécifier ici les classes du package Swing ou de tout autre package "classique" fourni avec le JDK. Par contre, si vous utilisez des bibliothèques non fournies par défaut (par exemple le VerticalFlowLayout de Borland). C’est également ici que l’on ajoutera à l’archive tous les fichiers non-java nécessaires.

4) Résolution des dépendances (2)

JarExport

Vous ne ferez rien ici si aucun package autre que les packages par défaut de Sun n’est nécessaire à votre programme. Sinon vous devrez décider du niveau d’inclusion. Je conseille d’inclure toutes les classes et toutes les ressources, on perd un peu en taille du fichier, mais on est sûr que tout fonctionnera !

5) Créer un fichier MANIFEST

Cette étape n’est pas nécessaire dans tous les cas, par exemple si vous avez choisi "Basic" à l’écran (1), le fichier manifest ne sera par défaut pas créé. Par contre pour "Application" il est nécessaire: le fichier Manifest indique, entre autres, à l’interpréteur Java quelle classe contient la méthode main(), condition nécessaire à l’auto-exécution de l’archive.

JarExport

Vous pouvez choisir d’inclure un Manifest que vous avez créé vous même, amis pourquoi se compliquer la vie quand JBuilder le génère tout seul comme un grand ?!

6) Spécifier la classe main()

JarExport

Un package, une archive, peuvent contenir plusieurs classes implémentant une méthode main(). On définit ici laquelle des ces méthodes main() devra être signalée au Manifest. On laissera cochée la case "Use the main class specified in the default runtime" par défaut. Lors de la première exécution d’un programme (à moins que l’ossature de ce programme n’ait été créée par JBuilder lui-même), JBuilder vous demande quelle est la classe principale du programme, et c’est cette classe, contenant la méthode main() dans le cas d’une application, qui sera utilisée pour lancer le programme sous JBuilder (en runtime normal ou en debug), et qui sera ici considérée comme la classe principale du programme à signaler comme telle au Manifest.

7) Observer

JarExport

On voit une nouvelle icône dans l’inspecteur d’objets. Notre archive s’appelle "Application", mais ne contient pas encore de fichier Jar. Pour créer réellement le fichier Jar nous devons "reconstruire" le programme.

8) Reconstruire

JarExport

Pour "reconstruire" on peut soir faire un clic-droit sur l’icône "Application" et choisir "Reconstruire" (ou "Rebuild" en version US) afin de créer le fichier JAR. On peut aussi utiliser le bouton de la barre d’icônes.

Ceci est très pratique: à chaque compilation, JBuilder recrée automatiquement le fichier JAR. Un exemple de compilation ci-dessous où l’on voit que JBuilder est en train de créer l’archive. (j’ai dû m’y reprendre à plusieurs fois pour faire la capture d’écran tellement que la création de cette archive, pour notre petit programme exemple, est rapide !)

JarExport

Tutoriel distribué pour le FAQ Java de Java-France www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG
Écrit à Montpellier le 3 juillet 2001

• 717 mots • #programmation #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
2 Juill 2001

Cet article de la FAQ a pour but de montrer comment télécharger un fichier depuis Internet vers son Disque Dur. On peut utiliser plusieurs méthodes, et celle à laquelle on pensera en premier lieu est sûrement d’implémenter un petit client FTP ou d’utiliser un JavaBean FTP comme celui d’IPWorks (dans JBuilder 5). Cependant, je propose ici une solution plus simple (beaucoup plus simple), à partir du moment où l’on connaît l’adresse exacte du fichier à télécharger. Cette méthode est également plus sécurisée, en cela que l’on a aucun besoin de spécifier un login et un mot de passe.

Nous allons donc utiliser une méthode avec URLConnection. Voici le code source commenté:

// Spécifier le chemin exact vers le fichier
URL u = new URL("http://www.monserveur.com:80/monrepertore/lisezmoi.txt");

// Ouvrir la connexion, début de la communication avec le serveur
URLConnection uc = u.openConnection();

// Récupérer la taille exacte en nombre d’octets du fichier désigné, et la stocker dans un int
int taille = uc.getContentLength();

// Créer un flux d’entrée pour le fichier
InputStream brut = uc.getInputStream();

// Mettre ce flux d’entrée en cache (pour un meilleur transfert, plus sûr et plus régulier).
InputStream entree = new BufferedInputStream(brut);

// Créer une matrice (un tableau) de bytes pour stocker tous les octets du fichier
byte[] donnees = new byte[taille];

// Pour l’instant aucun octet n’a encore été lu
int octetsLus = 0;

// Octets de déplacement, et octets déjà lus.
int deplacement = 0; float alreadyRead = 0;

// Boucle permettant de parcourir tous les octets du fichier à lire
while(deplacement < taille)
{
// utilisation de la methode "read" de la classe InputStream
octetsLus = entree.read(donnees, deplacement, donnees.length-deplacement);

// Petit calcul: mise à jour du nombre total d’octets lus par ajout au nombre d’octets lus au cours des précédents passages au nombre d’octets lus pendant ce passage
alreadyRead = alreadyRead + octetsLus;

// -1 marque par convention la fin d’un fichier, double opérateur "égale": = =
if(octetsLus == -1) break;

// se cadrer à un endroit précis du fichier pour lire les octets suivants, c’est le déplacement
deplacement += octetsLus;

}
// fermer le flux d’entrée.
entree.close();

// Récupérer le nom du fichier
String fichier = u.getFile();
fichier = fichier.substring(fichier.lastIndexOf(‘/’) + 1);

// Créer un fichier sur le DD afin d’y copier le contenu du fichier téléchargé (par un flux de sortie).
FileOutputStream fichierSortie = new FileOutputStream(fichier);

// copier…
fichierSortie.write(donnees);

// vider puis fermer le flux de sortie
fichierSortie.flush(); fichierSortie.close();

Tutoriel distribué pour le FAQ Java de Java-France www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Ecrit à Montpellier le 2 juillet 2001

• 470 mots • #programmation #serveur #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
27 Avr 2001

J’ai décidé de traiter ce point précis de la programmation Java: la convertion des types primaires (ou types de base) de données, car cela m’a posé des problèmes quand j’ai débuté en Java, et cela en pose souvent aux programmeurs venant de Delphi/Pascal, tout simplement car il n’existe pas en Java de méthodes comme IntToStr ou StrToInt (Delphi).
Je vous propose ici l’implémentation de ces deux méthodes, ainsi que deux autre méthodes convertissant des int vers long et des String vers float. Vous pourrez ensuite, une fois le schéma posé dans ce document, faire vous-même d’autres combinaisons.

Voici donc les méthodes ainsi que la manière de les utiliser:

Méthodes

/**
* De String vers INT
*/
public static int strToInt(String s)
{
Integer ger = new Integer(s);
int i = ger.intValue();
return i;
}

/**
* De INT vers String
*/
public static String intToStr(int i)
{
String texte = new String();
texte = texte.valueOf(i);
return texte;
}

/**
* De INT vers long
*/
public static long intToLong(int i)
{
Integer ger = new Integer(i);
long lg = ger.longValue();
return lg;
}

/**
* de String vers float
*/
public static float strToFloat(String s)
{
float f = Float.valueOf(s.trim()).floatValue();
return f;
}

Comment les utiliser

J’ai un champ de texte, un JTextField, dans lequel l’utilisateur entre une valeur numérique. Je veux récupérer cette valeur, lui ajouter 3, par exemple, et l’afficher dans un composant JLabel. Mon JTextField s’appelle textField, et mon JLabel, label. Voici le code que je dois écrire:

int monNombre;
monNombre = srtToInt(textField.getText());
monNombre = monNombre + 3;
label.setText(intToStr(monNombre);
Code réduit:
label.setText(intToStr(strToInt(textField.getText()) + 3));

Tutoriel distribué pour le FAQ Java de Java-France www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Ecrit à Montpellier le 27 avril 2001

• 364 mots • #programmation #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
22 Avr 2001

Ce chapitre de la FAQ Java explique, pas à pas, comment installer et configurer un environnement de développement et d’exécution de servlets et de pages JSP sur une machine tournant sous Windows 95/98/Me (NT/2000 ?).
Nous utiliserons le JSWDK de Sun (Java Servlets Web Development Kit). Vous pouvez aussi installer le serveur de Netscape ou Jakarta (pour Apache), mais nous nous centrerons ici sur l’inplémentation officielle de Sun.

1) Vous devez posséder un JDK installé et configuré sur votre machine.

2) Vous devez télécharger à partir du site de Sun le JSWDK en cliquant ici. Le fichier à télécharger est au format ZIP. C’est une archive et vous avez besoin d’un programme externe pour la décompresser, le shareware WinZip convient parfaitement.

JWSDK

3) Décompressez l’archive ZIP à la racine de votre disque dur en cochant la case "Use folders name" comme dans l’illustration ci-dessous:

4) Lancez "startserver.bat" à partir de la ligne de commande. Il s’agit du fichier de commandes qui lancera le serveur sur votre machine, il se trouve à la racine du répertoire d’installation du JSWDK. Voici ce qui devrait vous être retourné:

5) Vous pouvez maintenant utiliser le serveur et le tester dans un navigateur:
- ouvrez un navigateur web
- tapez dans la zone d’url: http://localhost:8080/ ou http://127.0.0.1:8080/
- une page d’accueil doit apparaître. Si c’est le cas, tout fonctionne bien, votre environnement de servlets est bien installé !

JWSDK

6) Nous allons maintenant le configurer ! Pour cela, ouvrez dans un éditeur de texte brut (pas de Microsoft Word ou autre chose du genre, utilisez NotePad !) le fichier "webserver.xml" situé à la racine du répertoire d’installation.
Vous n’avez normalement à changer les valeurs proposées qu’en cas de problème, ou si vous désirez paramétrer manuellement votre serveur. A titre indicatif, les valeurs par défaut sont les suivantes:

Port Number 8080
Bound IP Address all (tous)
Admin Port N’importe quel port entre 2048 et 8192
Document Base Une page html
Work directory for Temporary Files work par défaut
Session inactive max. interval 30 minutes

Tutoriel distribué pour le FAQ Java de Java-France www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Ecrit à Montpellier le 22 avril 2001

• 383 mots • #programmation #serveur #windows #java
"GF", "login"=>"gflorimond", "email"=>"[email protected]", "url"=>"http://www.valhalla.fr"}" itemtype="https://schema.org/Person" />
22 Avr 2001

Ce "How To" explique comment charger une URL, autrement dit une page web, à partir d’une applet Java, insérée dans une autre page web. Ceci ne posera aucun problème à un programmeur expérimenté dans la programmation des applets, mais, à cause des restrictions de sécurité desdites applets, cela peut en poser à des programmeurs qui ne seraient pas habitués à travailler avec Java sur Internet.
En effet, les applets Java sont conçues pour une sécrité de l’hôte optimale, il n’est donc pas possible de réaliser certaines opérations d’Entrée/Sortie comme par exemple lire ou écrire des fichiers sur l’ordinateur de l’hôte, ou sur un autre serveur que celui sur lequel est hébergée l’applet. C’est sur ce dernier point q’un problème peut se poser: la page web à charger peut ne pas être sur le même serveur que l’applet. Ainsi, si le code est mal écrit, une exception de sécurité sera générée, et la page ne sera pas chargée.
Nous allons voir ici comment faire pour éviter une telle exception. Le code à écrire est -très- simple et court, le voici commenté:

/*
Nous devons en premier lieu savoir dans quel contexte est exécutés l’applet, si s’agit, par exemple, de l’appletviewer ou d’un navigateur. S’il s’agit d’un navigateur, tout va bien !
*/
AppletContext navigateur = getAppletContext();

/*
Nous devons ensuite damander à ce navigateur, qui est maintenant en parlant programmtion, l’objet navigateur de type AppletContext, de charger une page.
Dans notre exemple l’URL chargée est http://www.jgflsoft.com, vous pouvez bien sûr l’adapter comme vous le désirez, tant que l’argument passé à la méthode showDocument() est de type String.
*/
navigateur.showDocument("http://www.java-france.com");

Et voilà, le tour et joué, la page se chargera, il vous suffit d’intégrer ces deux commandes dans un gestionnaire d’évènements ou dans une méthode !

Tutoriel distribué pour le FAQ Java de Java-France www.java-france.com / www.jgflsoft.com
Réédité pour Valhalla GFBLOG.
Ecrit à Montpellier le 22 avril 2001

• 331 mots • #programmation #java