Programmazione avanzata in Java - isib.cnr.itpaolo/didattica/corsojava/javabookB.pdf ·...

53
Programmazione avanzata in Java Paolo Bison Technical Report 13/00, LADSEB-CNR Padova, Italy, Novembre 2000. LADSEB-CNR Corso Stati Uniti 4 I-35127 Padova, Italy e-mail:[email protected] tel: 049 8295765 fax: 049 8295763

Transcript of Programmazione avanzata in Java - isib.cnr.itpaolo/didattica/corsojava/javabookB.pdf ·...

Programmazioneavanzatain Java

PaoloBison

TechnicalReport 13/00, LADSEB-CNRPadova, Italy , Novembre2000.

LADSEB-CNRCorsoStatiUniti 4

I-35127Padova,Italye-mail:[email protected]

tel: 0498295765fax: 0498295763

PREFAZIONE

In questorapportovengonodescrittele funzionalitapiu avanzatedel linguaggio Javaillustrandoleconesempiapplica-tivi. Verranno presentatila programmazioneconcorrentebasatasui threads,l’attivazione di programmiscritti in altrilinguaggi, l’interfacciagraficabasatasull’ AbstractWindow Systemed il metodo RemoteMethodInvocationper lacomunicazionetradiversemaccine virtuali java.

ABSTRACT

This report describes the advanced featuresof the Java language, suchas the concurrent programmingbasedonthreads, the native interface usedto call procedureswritten in otherprogramminglanguages,the AbstractWindowSystemusedto build graphical interfacesandtheRemoteMethodInvocationfor exchangingdatabetweenjavavirtualmachines.

INDICE

1 Abstract Window Toolkit (AWT) 11.1 Interfacciagrafica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.2 Uscitasustampante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.3 Un sempliceeditore di testi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

2 Multipr ogrammazione. 132.1 Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132.2 Loopstemporizzato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 RemoteMethod Invocation 153.1 Client Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 RobotNameService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213.3 InformationDelivery Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

4 Autoreferenzialit a 354.1 Matrici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 354.2 Calcolotempodi esecuzione. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

5 Programmi nativi 435.1 Stampamessaggio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435.2 Sommaedinversionedi unarray . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

Capitolo 1

Abstract Window Toolkit (AWT)

In questocapitolo sonomostratialcuni esempidi programmi che utilizzano le funzionalita del AbstractWindowToolkit (AWT) presentenel linguaggioJavaperla realizzazionedi interfacce grafiche.

AWT e un sistemabasatosu eventi e la tabellaseguente illustra a quali classidi eventi rispondiono i differentielmentigrafici.

action adjustment component container focus item key mouse mousemotion text window

Button X X X X X XCanvas X X X X X

Checkbox X X X X X XCheckboxMenuItem * X

Choice X X X X X XComponent X X X X XContainer X X X X X X

Dialog X X X X X X XFrame X X X X X X XLabel X X X X XList X X X X X X X

MenuItem XPanel X X X X X X

Scrollbar X X X X X XScrollPane X X X X X XTextArea X X X X X X

TextComponent X X X X X XTextField X X X X X X XWindow X X X X X X X

2 1. AWT

Listener Interface Adapter Class MethodsActionListener none actionPerformed

AdjustmentListener none adjustmentValueChangedComponentListener ComponentAdapter componentHidden

componentMovedcomponentResizedcomponentShown

ContainerListener ContainerAdapter componentAddedcomponentRemoved

FocusListener FocusAdapter focusGainedfocusLost

ItemListener none itemStateChangedKeyListener KeyAdapter keyPressed

keyReleasedkeyTyped

MouseListener MouseAdapter mouseClickedmouseEnteredmouseExitedmousePressedmouseReleased

MouseMotionListener MouseMotionAdapter mouseDraggedmouseMoved

TextListener none textValueChangedWindowListener WindowAdapter windowActivated

windowClosedwindowClosingwindowDeactivatedwindowDeiconifiedwindowIconifiedwindowOpened

1.1 Interfaccia grafica

Questoprogrammamostrai vari elementi graficichesi possonousarein unprogrammajava.

Listato 1.1- GUIW indow.java: elementidel AWT

import java.awt. *;import java.awt.event. *;

public class AWTtest extends Frame{

final String FDCMD = "File dialog...";final String QUITCMD = "Quit";

public AWTtest (){

/* creazione panel superiore */Panel bottomPanel = new Panel ();Panel centerPanel = new Panel ();

setLayout (new BorderLayout ());

MenuBar mb = new MenuBar ();

/* creazione di un menu */Menu m = new Menu ("Primo");

1. AWT 3

MenuItem mi = new MenuItem ("Menu A");mi.addActionListener (new ActionEventManager ());m.add (mi);

CheckboxMenuItem mcbi = new CheckboxMenuItem ("Menu B");mcbi.addItemListener (new ItemManager ());m.add (mcbi);

mi = new MenuItem ("Menu C");mi.addActionListener (new ActionEventManager ());m.add (mi);

m.add (new MenuItem ("-")); /* separatore */

mi = new MenuItem (FDCMD);mi.addActionListener (new FDManager ());m.add (mi);

m.add (new MenuItem ("-")); /* separatore */

mi = new MenuItem (QUITCMD);mi.addActionListener (new ActionEventManager ());m.add (mi);

mb.add (m); /* aggiungi menu alla barra dei menu */

/* creazione di un altro menu */m = new Menu ("Secondo");mi = new MenuItem ("Menu altro A");mi.addActionListener (new ActionEventManager ());m.add (mi);

mi = new MenuItem ("Menu altro B");mi.addActionListener (new ActionEventManager ());m.add (mi);

mb.add (m); /* aggiungi menu alla barra dei menu */

setMenuBar (mb); /* assegna la barra dei menu alla finestra */

//Add small things at the bottom of the window.bottomPanel.add (new TextField ("TextField"));bottomPanel.add (new Button ("Button"));bottomPanel.add (new Checkbox ("Checkbox"));

Choice c = new Choice ();c.addItem ("Scegli 0");c.addItem ("Scegli 1");c.addItem ("Scegli 2");bottomPanel.add (c);add ("South", bottomPanel);

//Add big things to the center area of the window.centerPanel.setLayout (new GridLayout (1, 2));

//Put a label and a text area in the right column.Panel p = new Panel ();

p.setLayout (new BorderLayout ());p.add ("North", new Label ("Label", Label.CENTER));p.add ("Center", new TextArea ("TextArea", 5, 20));centerPanel.add (p);

//Put a canvas in the left column.centerPanel.add (new testCanvas ());

4 1. AWT

add ("Center", centerPanel);

//Put�

a list on the right side of the window.List l = new List (3, false);for (int i = 1; i <= 10; i++)

{l.addItem ("List item " + i);

}add ("East", l);

addWindowListener (new WindowEventManager ());}

/**inner class per la gestione degli eventi

generatidalla finestra*/class WindowEventManager implements WindowListener{

public void windowClosing (WindowEvent e){

displayMessage ("Window closing", e);System.exit (0);

}

public void windowClosed (WindowEvent e){

displayMessage ("Window closed", e);}

public void windowOpened (WindowEvent e){

displayMessage ("Window opened", e);}

public void windowIconified (WindowEvent e){

displayMessage ("Window iconified", e);}

public void windowDeiconified (WindowEvent e){

displayMessage ("Window deiconified", e);}

public void windowActivated (WindowEvent e){

displayMessage ("Window activated", e);}

public void windowDeactivated (WindowEvent e){

displayMessage ("Window deactivated", e);}

void displayMessage (String prefix, WindowEvent e){

System.out.println (prefix+ ": "+ e.getWindow ()

);

1. AWT 5

}

}

/**inner class per la gestione degli action eventche possono essere genarati da un button, un menuitem, un textfield o un listitem*/

class ActionEventManager implements ActionListener{public void actionPerformed (ActionEvent e){

String cmd = e.getActionCommand ();System.out.println ("Perfom action: "

+ cmd);if (cmd.compareTo (QUITCMD) == 0)

System.exit (0);}

}

/**inner class per la gestione del file dialogche possono essere genarati da un button, un menuitem, un textfield o un listitem*/

class FDManager implements ActionListener{public void actionPerformed (ActionEvent e){

FileDialog fd = new FileDialog (AWTtest.this);fd.show ();

}}

/**inner class per la gestione del cambiamento di statodegli elementi di tipo check, choice o list */

class ItemManager implements ItemListener{public void itemStateChanged (ItemEvent e){

System.out.println ("Change state: "+ e.getItem ());

}}

public static void main (String args[]){AWTtest window = new AWTtest ();

window.setTitle ("AWT test");window.pack ();window.show ();

}

/**testCanvas

inner classe per definire qualcosa da disegnare*/

class testCanvas extends Canvas{

public void paint (Graphics g)

6 1. AWT

{int w = getSize ().width;int h = getSize ().height;

g.setColor (Color.red);g.drawRect (0, 0, w - 1, h - 1);g.drawString ("Canvas", (w - g.getFontMetrics ().stringWidth ("Canvas")) / 2,

10);

g.setFont (new Font ("Helvetica", Font.PLAIN, 8));g.drawLine (10, 10, 100, 100);g.fillRect (9, 9, 3, 3);g.drawString ("(10,10)", 13, 10);g.fillRect (49, 49, 3, 3);g.drawString ("(50,50)", 53, 50);g.fillRect (99, 99, 3, 3);g.drawString ("(100,100)", 103, 100);

}

/* se non si specificano i metodi seguenti la canvas qualchevolta non viene disegnata */public Dimension getMinimumSize (){

return new Dimension (200, 200);}public Dimension getPreferredSize (){

return getMinimumSize ();}

}}

1.2 Uscitasu stampante

Esempiodi comesi possanoutilizzarele funzionalitadi AWT perrealizzare unauscitagraficasustampante.

Listato 1.2- PrintTest.java: esempiodi stampa

import java.awt.*;

public class PrintTest extends Frame{

Frame printframe;

public PrintTest (String title){

super (title);printframe = new Frame ();printframe.setSize (200, 200);printframe.pack ();

}

/**event handler stile 1.0

*/

public boolean handleEvent(Event event) {if (event.id == Event.WINDOW_DESTROY)

1. AWT 7

System.exit(0);

return super.handleEvent(event);}

public static void main (String[]args){Graphics g;

try{

PrintTest mainframe = new PrintTest ("Print Test");mainframe.setSize (200, 200);mainframe.show ();

Color bg = mainframe.getForeground ();

String[] st = Toolkit.getDefaultToolkit ().getFontList ();for (int j = 0; j < st.length; j++)

System.out.println (st[j]);Font font = new Font ("Helvetica", Font.PLAIN, 12);

PrintJob pj =Toolkit.getDefaultToolkit ().getPrintJob (mainframe.printframe, "Print Test", null);if (pj != null)

{System.out.println ("PageDimension " + pj.getPageDimension ());System.out.println ("PageResolution " + pj.getPageResolution ());

// stampa due paginefor (int i = 1; i < 3; i++)

{g = pj.getGraphics ();

// assegna colore e font// se non sono presenti alcune primitive grafiche generano// una eccezione NullPointerg.setColor (bg);g.setFont (font);

g.drawString ("Pagina " + i, 50, 50);g.drawString ("Pagina " + i, 50, 75);if (i == 1){

g.drawRect (100, 100, 100, 100); // se non e’ presente viene stampata un linea extrag.drawOval (250, 250, 100, 100);

}else{

g.drawRect (200, 200, 100, 100);}

mainframe.printframe.printComponents (g);g.dispose (); // send to the printer

}pj.end ();

}else

System.out.println ("printing canceled!");}catch (Exception e){

System.out.println (e);}

}

8 1. AWT

}

1.3 Un sempliceeditoredi testi

Realizzazionedi un sempliceeditorperfile di testoutilizzantele funzionalita di manipolazionedi stringhepresentinelAWT.

Listato 1.3- TextEditor.java: un editoredi testi.

/** 1.1 version.

*/

import java.awt. *;import java.awt.event. *;import java.io. *;

public class TextEditor extends Frameimplements ActionListener, ItemListener

{boolean inAnApplet = true;TextArea output;PopupMenu popup;String newline;String clipboard;

public TextEditor (){

MenuBar mb;Menu mfile, medit, m3, m4, m4_1, m5;MenuItem miopen, miquit, mi3_1, mi3_2, mi3_3, mi3_4, mi4_1_1, mi5_1,

mi5_2, pmi1, pmi2, mi5_1_duplicate;MenuItem micut, micopy, mipaste, miselect;CheckboxMenuItem mi2_1;

addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {if (inAnApplet) {dispose();} else {System.exit(0);

}}});

newline = System.getProperty ("line.separator");

//Add regular components to the window.setLayout (new BorderLayout ()); //max space: output

output = new TextArea (5, 30);output.setEditable (true);add ("Center", output);

/* Label label = new Label("Try bringing up"+ " a popup menu!");add("North", label);

*///Build the menu bar.

mb = new MenuBar ();setMenuBar (mb);

1. AWT 9

//Build first menu in the menu bar.//Specifying the second argument as true//makes this a tear-off menu.

mfile = new Menu ("File", true);mb.add (mfile);miopen = new MenuItem ("Open ...");mfile.add (miopen);mfile.addSeparator ();miquit = new MenuItem ("Quit");mfile.add (miquit);

//Build second menu in the menu bar.medit = new Menu ("Edit");mb.add (medit);

// mi2_1 = new CheckboxMenuItem("Menu item 2_1");// m2.add(mi2_1);

micut = new MenuItem ("Cut");medit.add (micut);micopy = new MenuItem ("Copy");medit.add (micopy);mipaste = new MenuItem ("Paste");medit.add (mipaste);medit.addSeparator ();miselect = new MenuItem ("Select all");medit.add (miselect);

/* //Build help menu.m5 = new Menu("Help Menu");mb.setHelpMenu(m5);mi5_1 = new MenuItem("Menu item 5_1");mi5_1.setShortcut(new MenuShortcut(KeyEvent.VK_5));m5.add(mi5_1);mi5_2 = new MenuItem("Menu item 5_2");m5.add(mi5_2);

*///Make a popup menu.

popup = new PopupMenu ("A Popup Menu");add (popup);pmi1 = new MenuItem ("A popup menu item");popup.add (pmi1);mi5_1_duplicate =new MenuItem ("Duplicate of menu item 5_1",

new MenuShortcut (KeyEvent.VK_5));popup.add (mi5_1_duplicate);pmi2 = new MenuItem ("An item with a shortcut",

new MenuShortcut (KeyEvent.VK_6));popup.add (pmi2);

//Build third menu in the menu bar.m3 = new Menu ("Menu 3");mb.add (m3);mi3_1 = new MenuItem ("Menu item 3_1");m3.add (mi3_1);mi3_2 = new MenuItem ("Menu item 3_2");m3.add (mi3_2);m3.addSeparator ();mi3_3 = new MenuItem ("Menu item 3_3");m3.add (mi3_3);mi3_4 = new MenuItem ("Menu item 3_4");mi3_4.setEnabled (false);m3.add (mi3_4);

10 1. AWT

//Build fourth menu in the menu bar.m4 = new Menu ("Menu 4");mb.add (m4);m4_1 = new Menu ("Submenu 4_1");m4.add (m4_1);mi4_1_1 = new MenuItem ("Menu item 4_1_1");m4_1.add (mi4_1_1);

//Register as an ActionListener for all menu items.mfile.addActionListener (this);medit.addActionListener (this);m3.addActionListener (this);m4.addActionListener (this);mi4_1_1.addActionListener (this); //m4 can’t detect

//submenu actions// m5.addActionListener(this);

popup.addActionListener (this);

//Set action commands for a few menu items.miopen.setActionCommand ("open");miquit.setActionCommand ("quit");micut.setActionCommand ("cut");micopy.setActionCommand ("copy");mipaste.setActionCommand ("paste");miselect.setActionCommand ("select");

// mi5_1.setActionCommand("5_1");// mi5_2.setActionCommand("5_2");

pmi1.setActionCommand ("popup item #1");// mi5_1_duplicate.setActionCommand("5_1");

pmi2.setActionCommand ("popup item #2");

//Register as ItemListener on checkbox menu item.// mi2_1.addItemListener(this);

//Listen for when the popup menu should be shown.MouseListener listener = new PopupListener ();

addMouseListener (listener);output.addMouseListener (listener);

// label.addMouseListener(listener);}

class PopupListener extends MouseAdapter{

public void mousePressed (MouseEvent e){

maybeShowPopup (e);}

public void mouseReleased (MouseEvent e){

maybeShowPopup (e);}

private void maybeShowPopup (MouseEvent e){

if (e.isPopupTrigger ()){

popup.show (e.getComponent (),e.getX (), e.getY ());

}}

}

1. AWT 11

public void actionPerformed (ActionEvent e){/* output.append("\"" + e.getActionCommand()

+ "\" action detected in menu labeled \""+ ((MenuItem)(e.getSource())).getLabel()+ "\"." + newline); */

if (e.getActionCommand ().compareTo ("quit") == 0)System.exit (0);

else if (e.getActionCommand ().compareTo ("open") == 0){

FileDialog fd = new FileDialog (this);fd.show ();System.out.println (fd.getFile ());System.out.println (fd.getDirectory ());

if (fd.getFile () != null){

output.setText ("");setTitle ("TextEdit: " + fd.getDirectory () + fd.getFile ());loadFile (fd.getDirectory () + fd.getFile ());

}}

else if (e.getActionCommand ().compareTo ("select") == 0){

output.selectAll ();}

else if (e.getActionCommand ().compareTo ("copy") == 0){

clipboard = output.getSelectedText ();System.out.println (clipboard);

}else if (e.getActionCommand ().compareTo ("cut") == 0)

{clipboard = output.getSelectedText ();output.replaceRange ("", output.getSelectionStart (), output.getSelectionEnd ());

}else if (e.getActionCommand ().compareTo ("paste") == 0)

{output.insert (clipboard, output.getCaretPosition ());

}}

public void itemStateChanged (ItemEvent e){output.append ("Item state change detected on item \""

+ e.getItem ()+ "\" (state is "+ ((e.getStateChange () ==

ItemEvent.SELECTED) ?"selected).": "deselected).")

+ newline);}

public void loadFile (String fname){int r;char[] ch = new char[1];

try{

FileInputStream fin = new FileInputStream (fname);

12 1. AWT

try{while ((r = fin.read ()) != -1)

{// System.out.println (r);

ch[0] = (char) r;output.append (new String (ch));

}}catch (EOFException e){}fin.close ();

}catch (IOException e){

System.out.println ("IOex");}

}

public static void main (String[]args){

TextEditor window = new TextEditor ();

window.inAnApplet = false;window.setTitle ("TextEditor:");window.setSize (450, 200);window.setVisible (true);

}}

Capitolo 2

Multipr ogrammazione.

In java esistela possibilita di definirethreads, ovvero diverse linee di esecuzione presentiall’interno di uno stessoprogramma.E quindi possibilesviluppareprogrammiin cui diversi elementivengonoeseguiti in manieraconcorrente.

2.1 Loops

Esempiodi programmazioneconcorrentein cui vienecreatouncertonumerodi threads,ciascunodeiqualiesegue unciclo infinito di stampadi unmessaggio.

Listato 2.1- Loops.java: cicli infiniti

class Loops implements Runnable{Thread loopThread = null;String name;

Loops(String lname){name=lname;

}

public void start() {if (loopThread == null) {

loopThread = new Thread(this,name);loopThread.start();

}}

public void run(){while (true) System.out.println(name+" ") ; // loop for ever

}

public static void main (String[] args) {int nargs = args.length;int nloop;

if (nargs<1) nloop=4;else nloop= Integer.parseInt(args[0]);System.out.println("Creating "+nloop+" loops.");for(int i=0; i<nloop;i++){

System.out.println("Starting loop: LOOP"+i);new Loops("LOOP"+i).start();

}}

}

14 2. Multiprogrammazione

2.2 Loops temporizzato

Esempio� analogo a quello della sezioneprecedente, solo chein questocasoe definito il tempodi ciclo dei singolithreads.

Listato 2.2- TimedLoop.java: cicli temporizzati

class TimedLoop implements Runnable{Thread clockThread = null;

public void start() {if (clockThread == null) {

clockThread = new Thread(this, "Loop");clockThread.start();

}}

public void join(){try {clockThread.join();} catch (InterruptedException e){}

}

public void run(){long t0,t1,t2;t0=System.currentTimeMillis();while (true) {t1=System.currentTimeMillis();//while (t1-t0<250) t1=System.currentTimeMillis();System.out.println(t1-t0);t0=t1;t2=System.currentTimeMillis();

try {Thread.sleep(250-(t2-t1));

} catch (InterruptedException e){}

}}

public static void main (String[] args) {TimedLoop tl= new TimedLoop();tl.start();

// tl.join();

}}

Capitolo 3

RemoteMethod Invocation

RemoteMethodInvocationeunsistemachepermetteadapplicazioni scrittein Javaedeseguitecomesingoliprocessidi comunicaretradi lorosecondo unparadigmabasatosullaprogrammazioneadoggetti. E possibilescambiareoggettitra unaapplicazionee l’altra e invocare metodisuoggettiremoti, ovvero cherisiedonoin unaapplicazionechenone quellache invoca l’esecuzione del metodo. Essenzialmente e un estensionedell’ambientedi oggetti fornito dallinguaggio Java ad un insiemedi macchine virtuali Java cheattraversolo scambiodi informazioni condividono lospaziodegli oggettidefiniti remoti.

La programmazioneedutilizzo di oggetti remotisucui sia possibileinvocaredei metodi dapartedi altreappli-cazioninonecosi immediataesemplice,comenel casodi oggetti locali, madeveseguire unaprocedurabendefinita:

� per ogni oggettoi cui metodi possanoessereinvocati in maniera remotasi deve definireun interfaccia chedefiniscatali metodi

� ogni oggettochepossaesserescambiatotraapplicazioni differentideveimplementarel’interfaccia java.io.Serializable

� realizzare gli oggetticheimplementanole interfaccieremote

Inoltre nella fasedi generazionedi unaapplicazione, dopoaver compilatocon successotutte le classi,si deve es-eguire in comando rmic ClassName su tutte le classichedefinisconooggettiremoti. Questocomando creaduefile:ClassName Skel.classnecessarioall’applicazionein cui l’oggetto remoto risiedee ClassName Stub.classchevieneutilizzatodatuttequelleapplicazioni chevoglianointeragire conl’oggettoin maniera remota.

Infine si deve attivare,con il comando rmir egistry, un serviziodi namingper gli oggetti remoti. Tale serviziopermette ad applicazioni chevogliano utilizzareoggetti remoti di ottenere un riferimento a tali oggetti, chedevenoesserestati registrati in precedenzacon il serviziostesso. E da notarsi cheper motivi di sicurezza,oggetti remotipossonoessereregistratisolamenteconunserviziodi naming chesiaattivo sulmedesimohostsucui l’oggettoremotorisiede.

3.1 Client Server

Sempliceesempiodi unaarchitettura client-server realizzatautilizzandole funzionalita del RMI. In questocasovi eunserver, realizzatocomeoggettoremoto, cheforniscedei serviziadunoo piu clienti. I serviziforniti ai clienti sonosolamentedue:il nomedelserverstessoedunasempliceelaborazionedi informazionericevutadal cliente.

��������� �������

��� ����� ���������

��

Figura3.1: Architetturaclient server

16 3. RemoteMethodInvocation

La figura3.1 mostrale relazioni ed il loro ordinedi occorrenzatra i vari moduli checostituisconol’intera con-figurazione. All’inizio il server registrasestessoconil serviziodi naming(0), poi un cliente,dopo aver ottenutounriferimentoal server interrogando il serviziodi naming (1), puo interagire conil server richiedendounservizio(2).

L’interfacciaServerIntf mostratanel listato 3.1 definiscei metodi remoti associaticon i dueservizi offerti dalserver.

Listato 3.1- ServerIntf .java: definizionedei serizi

/**ServerIntf.java

interfaccia che definisce i metodi del server che possonoessere invocati da remoto*/

import java.rmi. *;

public interface ServerIntf extends Remote{public String serverName () throws RemoteException;

/*ritorna il nome del server

*/

public Datum compute (Datum sth) throws RemoteException;/*

ritorna un informazione di tipo Datum ottenuta elaborandoun’informazione sempre di tipo Datum ricevuta dal cliente

*/}

La classeDatum.java rappresental’inf ormazione scambiatatra i clienti ed il server ede costituitadaduecampi:unastringaedunvalore numerico.

Listato 3.2- Datum.java: definizioneinformazionescambiata

/**Datum.java

classe che implemeta il tipo di informazione scambiata tra clientied il server.Tale informazione costituita da due campi:una stringa ed un valore intero

*/

class Datum implements java.io.Serializable{String name = "pluto" /*valore di default */ ;int value;

/*costruttoreil parametro s e‘ il valore da assegnare al campo name

*/Datum (String s)

{name = s;

}

/**metodo per assegnare un valore al campo numerico

3. RemoteMethodInvocation 17

*/void setValue (int i){value = i;

}

/**metodo che ritorna il valore del campo numerico*/

int getValue (){return value;

}

/**conversione al tipo String*/

public String toString (){return name + " " + value;

}

}

Nel listato3.3e mostratoil programmaperil server

Listato 3.3- Server.java: il programma server

/**Server.java

realizzazione del programma server

*/

import java.util. *;import java.rmi. *;import java.net. *;import java.rmi.server. *;

public class Server extends UnicastRemoteObject/* tutti gli oggetti che possono essere invocati in maniera remota devono

essere sottoclassi della classe UnicastRemoteObject */implements ServerIntf /* interfaccia che definisce i metodi remoti */

{String myName;

/**costruttore*/

public Server () throws RemoteException{

// il nome del server e’ il nome del host su cui giratry{

// ottieni nome dell’hostString fullHostName = InetAddress.getLocalHost ().getHostName ();// calcola posizione del primo .int idx = fullHostName.indexOf (’.’);

18 3. RemoteMethodInvocation

//estrai nome senza dominiomyName = fullHostName.substring (0, idx);

}catch (Throwable e){

myName = "noHost";}

}

/**realizzazione del servizio che ritorna il nome del server*/public String serverName (){

return myName;}

/**realizzazione del servizio che elabora i dati ricevuti dal cliente*/public Datum compute (Datum sth){

// crea nuovo datoDatum temp = new Datum ("Server");

// stampa il dato ricevuto dal clienteSystem.out.println ("Received " + sth);

// elabora: incrementa di uno il valore ricevuto dal clientetemp.setValue (sth.getValue () + 1);

// ritorna al cliente il risultato dell’elaborazionereturn temp;

}

/**programma principale*/public static void main (String[]args){

try{

/* installa un security manager. E’ obbligatorioquando si utilizzano le funzionalita’ del RMI */

RMISecurityManager security = new RMISecurityManager ();System.setSecurityManager (security);

/* crea il server */Server theServer = new Server ();

/* registra il server nel rmiregistry della macchina localecon il nome Server */

Naming.rebind ("Server", theServer);

/* stampa messaggio */System.out.println ("Server ready!");

}catch (Throwable e){

System.out.println ("exception: " + e);System.exit (1);

}}

}

3. RemoteMethodInvocation 19

mentrenel listato3.4quellodeiclienti:

Listato 3.4- Client.java: il programma client

/**Client.java

realizzazione del programma client

il programma viene attivato con il comando

java Client [-h host] value

dove host e’ il nome del calcolatore su cui risiede il server.Se non e’ presente si usa localhostvalue e’ il valore intero che verra utilizzato nel dato che ilcliente inviera’ al server*/

import java.rmi. *;import java.rmi.server. *;

public class Client{

/**programma principale

*/public static void main (String[]args){

String RMIRegHost;/* nome del host su cui e’ il server */int value; /* valore iniziale campo numerico */

if (args.length < 3){

RMIRegHost = "localhost";value = Integer.parseInt(args[0]);

}else {

RMIRegHost = args[1];value = Integer.parseInt(args[2]);}

try{

/* installa un security manager. E’ obbligatorioquando si utilizzano le funzionalita’ del RMI */

RMISecurityManager security =new RMISecurityManager ();

System.setSecurityManager (security);

/* creazione del dato da inviare al server*/Datum myDatum = new Datum ("Client");

myDatum.setValue (value);

/* nome del server nel RMI registry*/String RMIRegName = "Server";

/* URL per accedere al RMI registry

20 3. RemoteMethodInvocation

tale url e’ costituito dal protocollo rmi seguito dal nome del hoste dal nome dell’oggetto */

String name = "rmi://" + RMIRegHost + "/" + RMIRegName;

/* interrogazione del RMI registry per ottenere un riferimento al server */ServerIntf theServer = (ServerIntf) Naming.lookup (name);

/* stampa del nome del server ottenuto attivando un metodo remoto */System.out.println ("Server name: " + theServer.serverName ());

/* stampa del dato che il cliente invia al server */System.out.println (myDatum);

/* stampa del dato ricevuto dal server e che si ottieneutilizzando un metodo remoto */

System.out.println (theServer.compute (myDatum));

}catch (Throwable e){

System.out.println ("exception: " + e);System.exit (1);

}}

}

La compilazionedi questimoduli aviieneconi seguenti comandi:

javac ServerIntf.javajavac Client.javajavac Server.javarmic Server

Perl’esecuzionesi deveprimaattivare il serviziodi namingsullamacchina sucui sara disponibile il server conilcomando:

sun450% rmiregistry &sun450%

dove sun450% e il prompt del calcolatoreil cui nome e appunto sun450. Quindi si puo attivare il server con ilcomandojava Server ottenendo:

sun450% java ServerServer ready!

Clienti possono essereattivati siasul nodo sucui vi e il server

sun450% java Client 33Server name: sun450Client 33Server 34sun450%

siadaaltri calcolatori(in questocasodal nodo sun1)

sun1% java Client -h sun450 23Server name: sun450Client 23Server 24sun1%

E’ importantericordarsichequandosi fannodellemodificheal codice,si deveterminareil processormiregistrychefornisceil serviziodi namingaltrimentinonsi ottieneun funzionamento corretto. Perfarequestosi deve,utilizzandoil comandops,individuaretaleprocessoedil processojavachehaattivato

3. RemoteMethodInvocation 21

sun450% psPID TTY TIME CMD344 pts/0 0:00 csh377 pts/0 0:00 rmiregis384 pts/0 0:01 java

sun450%

edabortire il processojava

sun450% kill -9 384sun450% Killed

[1] Exit 137 rmiregistrysun450%

3.2 Robot NameService

Estensionedel sistemaclient-server illustrato nella sezioneprecedentead un sistemacon un numero illimitato diclientseservers.

E statoaggiunto unserverdi gestionedeiserverperpermettereai clientsdi ottenere unriferimento al servera cuivogliono collegarsi.

!#"%$'&)(+*-,/.10/&32 !#46574809;:+<�(= (+&3>?,/@1(

!#(A<B4-0/(+CED�0FGH H H 9

GH H H "

!#4657480F

F

GI G I

J

Figura3.2: Architettura delsistemaRobotNameService

Listato 3.5- RobotNameServiceIntf .java: servizi del Robot NameService

/**RobotNameServiceIntf.java

interfaccia che definisce i metodi remoti associati ai serviziforniti dal Robot Name Service

*/

import java.rmi. *;

public interface RobotNameServiceIntf extends Remote{

public void register (String name, RobotIntf robot) throws RemoteException;/* registra l’oggetto robot con il nome name */

public RobotIntf lookup (String name) throws RemoteException;/* ritorna un riferimento al robot associato al nome name */

}

22 3. RemoteMethodInvocation

Listato 3.6- RobotNameService.java: il programma per il Robot NameService

/**RobotNameService.java

servizio di naming per robot mobilimantiene un associazione robot-nome e permette di inserie un associazioneo di cercare il robot associato ad un dato nome*/

import java.util. *;import java.rmi. *;import java.rmi.server. *;import java.rmi.registry. *;

public class RobotNameService extends UnicastRemoteObjectimplements RobotNameServiceIntf

{/* costante che indica il massimo numero di associazioni */static final int max = 10;

String names[]; /* nomi dei robot */RobotIntf robots[]; /* riferimenti ai robot */int idx; /* indice che indica il numero di associazioni inserite */

/**costruttore

*/public RobotNameService () throws RemoteException{

super ();idx = 0; /* nessuna associazione */

/* alloca array per i dati delle associazioni */names = new String[max];robots = new RobotIntf[max];

}

/**inserimento di una associazione robot-nome

*/public void register (String name, RobotIntf robot){

System.out.println ("Registering " + name);names[idx] = name;robots[idx++] = robot;

}

/*ricerca di un robot, dato un nome

*/public RobotIntf lookup (String name){

int i;System.out.println ("Lookup " + name);

for (i = 0; i < idx; i++)if (names[i].equals (name))

break;if (i != idx)

return robots[i];else

return null;}

3. RemoteMethodInvocation 23

/**programma principale*/

public static void main (String[]args){

try{

/* installa un security manager. E’ obbligatorioquando si utilizzano le funzionalita’ del RMI */

RMISecurityManager security =new RMISecurityManager ();

System.setSecurityManager (security);

RobotNameService rns = new RobotNameService ();

/* ottieni riferimento al rmiregistry */Registry theRegistry = LocateRegistry.getRegistry ();

/* registra il Robot Name Service nel rmiregistry con il nome RNS */theRegistry.rebind ("RNS", rns);

/* stampa messaggio */System.out.println ("The RNS is ready!");

/* d’ora in poi attendi che qualcuno richieda un tuo servizio */

}catch (Throwable e){

System.out.println ("exception: " + e);System.exit (1);

}}

}

Listato 3.7- RobotIntf .java: i comandi del robot

/**RobotIntf.java

interfaccia che definisce i etodi remoti associati alle azioni che un robot mobilepuo’ eseguire*/

import java.rmi. *;

public interface RobotIntf extends Remote{

public RobotState getStatus () throws RemoteException;/* ritorna lo stato del robot */

public void go () throws RemoteException;/* abilita il robot a muoversi */

public void stop () throws RemoteException;

24 3. RemoteMethodInvocation

/* ferma il robot */

publicK void reset () throws RemoteException;/* esegue un reset dello stato del robot */}

Listato 3.8- RobotState.java: lo statodel robot

/**RobotState.java

rappresentazione dello stato di un robot*/class RobotState implements java.io.Serializable{

/*nome del robot */String name;

/* valori dell’odometria */float x, y, th;

/**costruttore

*/RobotState (String aname)

{name = aname;x = y = th = 0.0f;

}

/**reset dell’odometria*/synchronized void reset (){

x = y = th = 0.0f;}

/**modifica dell’odometria*/synchronized void update (float new_x, float new_y, float new_th){

x = new_x;y = new_y;th = new_th;

}

/* i due metodi precedenti sono synchronized per evitare conflittinell’assegnazione dei valori alle medesime variabili */

/**conversione a stringa

*/public String toString (){

return name + " " + x + " " + y + " " + th;}

3. RemoteMethodInvocation 25

}

Listato 3.9- Robot.java: il programma robot

/**Robot.java

il programma robot e’ una simulazione di un robot mobile.Una volta registratosi con il Robot Name Service il robotrimane in attesa che qualcuno richieda da remoto l’esecuzionedi uno dei metodi definiti nell’interfaccia RobotIntf.Alcuni di questi metodi possono attivare o disattivare un thread cherappresenta il ciclo di controllo dove lo stato del robot vienemodficato.*/

import java.util. *;import java.net. *;import java.rmi. *;import java.rmi.server. *;import java.rmi.registry. *;

public class Robot extends UnicastRemoteObjectimplements RobotIntf

{

/* costante con il nome del host su cui vi e’ il rmiregistry */static final String RNSHost = "sun450.ladseb.pd.cnr.it";

/* variabili locali del robot */String myName; /* nome del robot */RobotState myState; /* stato del robot */RobotControl cloop; /* thread del ciclo di controllo */

/**costruttore

*/public Robot (String name) throws RemoteException{myName = name;myState = new RobotState (name);cloop = new RobotControl ();

}

/**implementazione dei metodi dell’interfaccia RobotIntfsono i metodi che possono essere attivati da remoto*/

public RobotState getStatus (){return myState;

}

public void go (){System.out.println (myName + " starts moving");cloop.start ();

}

26 3. RemoteMethodInvocation

public void stop (){

cloop.stopK ();System.out.println (myName + " stopped");

}

public void reset (){

myState.reset ();}

/**classe che realizza il ciclo di controllo

esempio di inner class, ovvero definita all’interno di un’altra classe*/class RobotControl implements Runnable{

/* thread per il controllo */Thread controlThread;

/**attivazione del ciclo*/

public void start (){

if (controlThread == null){

controlThread = new Thread (this, "cloop");controlThread.start ();

}}

/**disattivazione del ciclo*/

public void stop (){

controlThread = null;}

/**routine che costituisce il coprpo del thread

*/public void run (){

Thread myThread = Thread.currentThread ();/* cicla finche’ controlThread non viene messo a null */

while (myThread == controlThread){

/* stampa nome del robot */System.out.println (Robot.this.myName);

/* modifica stato incrementando coordinate x e y */Robot.this.myState.update (Robot.this.myState.x + 50.3f,

Robot.this.myState.y + 33.3f,0.0f);

try{

/* dorme per 2.5 seconds */Thread.sleep (2500);

}

3. RemoteMethodInvocation 27

catch (InterruptedException e){}

}}

}

/**programma principale

*/public static void main (String[]args){

/* se non vi e’ il nome del robot esci con errore */if (args.length < 1)

{System.out.println ("Robot name needed");System.exit (1);

}

/* prendi il proprio nome dalla linea di comando */String name = args[0];

try{

/* installa un security manager. E’ obbligatorioquando si utilizzano le funzionalita’ del RMI */

RMISecurityManager security =new RMISecurityManager ();System.setSecurityManager (security);

/* crea l’oggetto robot */Robot thisRobot = new Robot (name);

/* ottieni riferimento al rmiregistry */Registry theRNSRegistry = LocateRegistry.getRegistry (RNSHost);

/* ottieni riferimento al Robot Name Service meorizzato nel rmiregistrycon il nome RNS */

RobotNameServiceIntf rns = (RobotNameServiceIntf) theRNSRegistry.lookup ("RNS");

/* registra se stesso con il Robot Name Service */rns.register (name, (RobotIntf) thisRobot);

/* stampa per avvertire che e’ ready */System.out.println ("The robot " + name + " is ready!");

/* d’ora in poi il robot attende che qualcuno richieda l’esecuzionedi un metodo remoto */

}catch (Throwable e){

System.out.println ("exception: " + e);System.exit (1);

}}

}

Listato 3.10 - RemoteCnt.java:il controllo remoto

28 3. RemoteMethodInvocation

/**RemoteCnt.java

programma di controllo di un robot.si attiva con il comando:java RemoteCnt nomerobot

il programma, dopo aver ottenuto un riferimento al robot associato al nome nomerobotdal Robot Name Service, permette all’utente di interagire con il robot attraversoun insieme di comandi che vengono eseguiti dal robot. Inoltre stampa il tempodi esecuzione di tali comandi. Tale tempo comprende anche l’overhead dovutoal protocollo RMI

*/

import java.io. *;import java.rmi. *;import java.rmi.registry. *;

public class RemoteCnt{

/* costante con il nome del host su cui vi e’ il rmiregistry */static final String RNSHost = "sun450.ladseb.pd.cnr.it";

/* riferimento al robot controllato */static RobotIntf theRobot;

/**stampa del menu utente

*/static void printMenu (){

System.out.println ();System.out.println ("RemoteCnt Menu");System.out.println ();System.out.println ("i : print robot’s status");System.out.println ("g : motion start");System.out.println ("s : motion stop");System.out.println ("r : reset the robot");System.out.println ("q : quit the program");

}

/**gestione dell’interfaccia utente

*/static void userInterface (){

RobotState theState;boolean loopFlag = true;int ch;long t0, t1;

printMenu ();try

{while (loopFlag){

System.out.print (">");/* lettura comando (un carattere) */

ch = System.in.read ();

/* scelta del comando da eseguire */switch (ch)

3. RemoteMethodInvocation 29

{case ’q’:

{loopFlag = false;break;

}case ’i’:

{t0 = System.currentTimeMillis ();theState = theRobot.getStatus (); /* esecuzione remota */t1 = System.currentTimeMillis ();System.out.println ("Info: " + theState);System.out.println ("Done in " + (t1 - t0) + " millisec.");break;

}case ’g’:

{t0 = System.currentTimeMillis ();theRobot.go (); /* esecuzione remota */t1 = System.currentTimeMillis ();System.out.println ("Done in " + (t1 - t0) + " millisec.");break;

}case ’s’:

{t0 = System.currentTimeMillis ();theRobot.stop (); /* esecuzione remota */t1 = System.currentTimeMillis ();System.out.println ("Done in " + (t1 - t0) + " millisec.");break;

}case ’r’:

{t0 = System.currentTimeMillis ();theRobot.reset (); /* esecuzione remota */t1 = System.currentTimeMillis ();System.out.println ("Done in " + (t1 - t0) + " millisec.");break;

}default:

printMenu ();}

/* leggi fino a fine linea */while (ch != ’\n’)

ch = System.in.read ();}

}catch (IOException e){}

}

/**programma principale

*/

public static void main (String[]args){

/* esci segnalando errore se non vi e’ il nome del robot */if (args.length < 1)

{

30 3. RemoteMethodInvocation

System.out.println ("Robot name needed");System.exit (1);

}

try{

/* installa un security manager. E’ obbligatorioquando si utilizzano le funzionalita’ del RMI */

RMISecurityManager security =new RMISecurityManager ();System.setSecurityManager (security);

/* ottieni riferimento al rmiregistry */Registry theRMIRegistry = LocateRegistry.getRegistry (RNSHost);

/* ottieni riferimento al Robot Name Service meorizzato nel rmiregistrycon il nome RNS */

RobotNameServiceIntf rns = (RobotNameServiceIntf) theRMIRegistry.lookup ("RNS");

/* ottieni riferimento al robot dal Robot Name Service */theRobot = rns.lookup (args[0]);

/* se il riferimento non e’ nullo attiva l’interfaccia utente */if (theRobot != null)userInterface ();

/* altrimenti esci con messaggio di errore */elseSystem.out.println ("Robot " + args[0] + " not found in the RNS");

}catch (Throwable e){

System.out.println ("exception: " + e);System.exit (1);

}}

}

La compilazionedi questimoduli aviieneconi seguenti comandi:

javac RobotIntf.javajavac RobotNameServiceIntf.javajavac RemoteCnt.javajavac Robot.javajavac RobotNameService.javarmic Robotrmic RobotNameService

3.3 Inf ormation Delivery Service

Esempiodi scambiodi informazione da uno a molti attraversol’uso di un server per la distribuzione di tale infor-mazione.

Listato 3.11- Inf oIntf .java: interfaccia per ricevere l’inf ormazione

/**InfoIntf.java

*/

3. RemoteMethodInvocation 31

LNMPOQ6R�SUT�VXW�QY OZ\[]^%R�_�T'`�RaQYb R�Q6`UT�c�R

OZ\[]UdeV�RaQf

ghih3hkj

f

g l m m m mn

Figura3.3: Architetturadel sistemadi InfoDelivery

import java.rmi.*;

public interface InfoIntf extends Remote {public void setInfo(Info sth) throws RemoteException;public void test(String n) throws RemoteException;}

Listato 3.12- Inf oDeliveryServiceIntf .java: interfaccia per il server

/**InfoDeliveryServiceIntf.java

*/

import java.rmi.*;

public interface InfoDeliveryServiceIntf extends Remote {public boolean register(InfoIntf user) throws RemoteException;public Info getInfo() throws RemoteException;}

Listato 3.13- Inf oDeliveryService.java: il programma server

/**InfoDeliveryService.java

*/

import java.util.*;import java.rmi.*;import java.rmi.server.*;import java.rmi.registry.*;

public class InfoDeliveryService extends UnicastRemoteObjectimplements InfoDeliveryServiceIntf {

static final public int MAX_USERS=10;

32 3. RemoteMethodInvocation

InfoIntf users[];int idx;

SendInfoLoop infoCnt;Info myInfo;

public InfoDeliveryService() throws RemoteException{super();idx=0;users = new InfoIntf[MAX_USERS];myInfo = new Info();myInfo.genera();infoCnt = new SendInfoLoop();

}

public Info getInfo(){return myInfo;}

synchronized public boolean register(InfoIntf user){System.out.println("Registering a user");if (idx==MAX_USERS) return false;users[idx++]=user;return true;}

synchronized int getNumUsers(){return idx;}

void start(){if (infoCnt!=null)infoCnt.start();}

class SendInfoLoop implements Runnable{Thread infoLoopThread;

public void start(){if (infoLoopThread==null) {infoLoopThread = new Thread(this,"infoloop");infoLoopThread.start();}}

public void stop(){infoLoopThread=null;}

public void run(){Thread myThread = Thread.currentThread();int local_idx=0;while (myThread == infoLoopThread){try{

myInfo.genera();local_idx= getNumUsers();

for(int i=0;i<local_idx;i++)try{if (users[i]!=null) users[i].setInfo(myInfo);} catch (Throwable e) {System.out.println("user error " +e);users[i]=null;}

3. RemoteMethodInvocation 33

Thread.sleep(5000); // waits 5 seconds} catch (Throwable e){System.out.println("excpetion: "+e);System.exit(1);}}}}

public static void main(String[] args){

try {RMISecurityManager security =

new RMISecurityManager();System.setSecurityManager(security);

InfoDeliveryService ids = new InfoDeliveryService();Registry theRegistry = LocateRegistry.getRegistry();theRegistry.rebind("IDS",ids);ids.start();System.out.println("IDS is ready!");} catch (Throwable e) {System.out.println("exception: "+e);System.exit(1);}}}

Listato 3.14- Inf oUser.java: programma cliente del Inf oDeliveryService

/**InfoUser.java

args[0] = hostname whre the delivery service runs, ifthe argument is present, otherwise localhost is used

*/

import java.util.*;import java.net.*;import java.rmi.*;import java.rmi.server.*;import java.rmi.registry.*;

public class InfoUser extends UnicastRemoteObjectimplements InfoIntf {

static String IDSHost="localhost";

Info myInfo;

public InfoUser() throws RemoteException{super();}

public void setInfo(Info newInfo){//myInfo.copy(newInfo);System.out.println("Info received :"+newInfo);

34 3. RemoteMethodInvocation

}

public void test(String n){System.out.println("test received :"+n);}

public static void main(String[] args){

if (args.length>0) IDSHost = args[0];

try {RMISecurityManager security =

new RMISecurityManager();System.setSecurityManager(security);

InfoUser thisUser = new InfoUser();

Registry theRNSRegistry = LocateRegistry.getRegistry(IDSHost);InfoDeliveryServiceIntf ids =(InfoDeliveryServiceIntf) theRNSRegistry.lookup("IDS");//System.out.println(ids.getInfo());if (ids.register((InfoIntf)thisUser))System.out.println("Waiting for info...");else {System.out.println("Delivery Service not available");System.exit(1);}} catch (Throwable e) {System.out.println("exception: "+e);System.exit(1);}}}

Capitolo 4

Autoreferenzialita

Nel linguaggiojava e possibileaccederee manipolaregli elementi,quali variabili e metodi, presentinelleclassichedefiniscono gli oggetti utiliizati in unparticolareprogramma.E cosi possibilecostruire programmichefunzionanoinmanieraindipendentedaglioggetti chedevono manipolareo concui devono interagire.

4.1 Matrici

In questasezionevieneillustratounprogrammapereseguire operazioni matriciali cheoperain manieraindipendentedal tipo (intero, realeo complesso)degli elementidellamatrice.

Listato 4.1- Matrix.j ava - superclassdellematrici

import java.lang.reflect.*;

/*** superclass per le matrici** @author P.Bison Copyright 1997**/

public class Matrix {

int righe; /* numero di righe */int colonne; /* numero di colonne */Object[][] data;

/* constructors */protected Matrix (){righe=colonne=0;data=null;}

protected Matrix (int n,int m){righe=n;colonne=m;data=new Object[n][m];}

protected void setMatrix(int n, int m) {righe=n;colonne=m;data=new Object[n][m];}

/*** somma due matrici* @param x il secondo operando della somma

36 4. Autoreferenzialita

* @return una matrice il cui valore e’ this+x*/publicK Matrix add (Matrix x)throws Exception

{Class methodclass;Method addmethod = null;Class partypes[]= new Class[3];Object parlist[] = new Object[3];boolean trovato=true;Matrix oper1,oper2,ris;int i,j;

if ((righe != x.righe) || (colonne != x.colonne))throw new ArithmeticException ("Incompatible matrix");

// ottieni la classe dell’oggetto (this)// e guarda se ha il metodooper1=this; oper2=x;methodclass= this.getClass();partypes[0] = Class.forName("java.lang.Integer");partypes[1] =Class.forName("java.lang.Integer");partypes[2] = x.data[0][0].getClass();try {

addmethod= methodclass.getMethod("addElement",partypes);} catch (NoSuchMethodException exceptionRef) {

trovato = false;}

if (!trovato) {// cerca nella classe del parametro (x)trovato = true;oper1=x; oper2 = this;methodclass= x.getClass();partypes[2] = this.data[0][0].getClass();try {addmethod= methodclass.getMethod("addElement",partypes);

} catch (NoSuchMethodException exceptionRef) {trovato = false;

}}

if (trovato) {ris = (Matrix) methodclass.newInstance(); // alloca risultatoris.setMatrix(righe,colonne); //for(i=0;i<righe;i++)for(j=0;j<colonne;j++) {

parlist[0]=new Integer(i);parlist[1]=new Integer(j);parlist[2]=oper2.data[i][j];ris.data[i][j] = addmethod.invoke(oper1,parlist);}

return ris;}

else return null;}

/*** converte una matrice in una stringa* @return una stringa che rappresenta il numero complesso*/public String toString (){

4. Autoreferenzialita 37

String matrep = "[";int i, j;

for (i = 0; i < righe; i++){

matrep += "[";for (j = 0; j < colonne; j++){

matrep = matrep + (data[i][j]==null ? "NULL" : data[i][j].toString());if (j != colonne - 1)

matrep += ",";}

matrep += "]";}

matrep += "]";return matrep;

}

/*** metodo principale*/public static void main (String[]args)throws Exception{Matrix mat1,mat2,mat3,ris;double[][] a ={{1.2, -0.75, 1.8},

{-0.99, 3.45, -4.89},{-9.8, 0.08, 1.98}};

int[][] a1 ={{1, 0, 0},{0, 1, 0},{0, 0, 1}};

mat1= new MatrixInt(a1); // alloca matrice interaSystem.out.println("mat1 = "+mat1);mat2= new MatrixDouble(a); // alloca matrice doubleSystem.out.println("mat2 = "+mat2);mat3= new MatrixComplex(a,a); // alloca matrice complessaSystem.out.println("mat3 = "+mat3);ris= mat1.add(mat1); // somma due matrici intereSystem.out.println("mat1 + mat1 = "+ris);ris= mat2.add(mat2); // somma due matrici doubleSystem.out.println("mat2 + mat2 = "+ris);ris= mat1.add(mat2); // somma una matrice intera con una doubleSystem.out.println("mat1 + mat2 = "+ris);ris= mat1.add(mat3); // somma una matrice intera con una complexSystem.out.println("mat1 + mat3 = "+ris);ris= mat3.add(mat2); // somma una matrice complex con una doubleSystem.out.println("mat3 + mat2 = "+ris);

}

} // end of class Matrix

Listato 4.2- MatrixInt.j ava - matrici conelementi interi

public class MatrixInt extends Matrix {

public MatrixInt(int n, int m) {

super(n,m);

38 4. Autoreferenzialita

for(int i=0;i<n;i++)for(int j=0;j<m;j++) data[i][j] = new Integer(0);

}

public MatrixInt() {

super();}

public MatrixInt (int[][]initdata){

super(initdata.length,initdata[0].length);for (int i = 0; i < righe; i++)

for (int j = 0; j < colonne; j++)data[i][j] = new Integer(initdata[i][j]);

}

public Integer addElement(Integer intI, Integer intJ, Integer x){int i = intI.intValue();int j = intJ.intValue();

return new Integer(((Integer)data[i][j]).intValue()+x.intValue());}

} /* end of class MatrixInt */

Listato 4.3- MatrixDo uble.java - matrici conelementireali

public class MatrixDouble extends Matrix {

public MatrixDouble() {

super();}

public MatrixDouble(int n, int m) {

super(n,m);for(int i=0;i<n;i++)

for(int j=0;j<m;j++) data[i][j] = new Double(0);}

public MatrixDouble (double[][]initdata){

super(initdata.length,initdata[0].length);for (int i = 0; i < righe; i++)

for (int j = 0; j < colonne; j++)data[i][j] = new Double(initdata[i][j]);

}

public Double addElement(Integer intI, Integer intJ, Double x){int i = intI.intValue();int j = intJ.intValue();

return new Double(((Double)data[i][j]).doubleValue()+x.doubleValue());}

4. Autoreferenzialita 39

public Double addElement(Integer intI, Integer intJ, Integer x){int i = intI.intValue();int j = intJ.intValue();

return new Double(((Double)data[i][j]).doubleValue()+x.intValue());}

}

Listato 4.4- MatrixCo mplex.java - matrici con elementicomplessi

public class MatrixComplex extends Matrix {

public MatrixComplex() {

super();}

public MatrixComplex(int n, int m) {

super(n,m);for(int i=0;i<n;i++)for(int j=0;j<m;j++) data[i][j] = new Complex();

}

public MatrixComplex(double[][] initReale, double[][] initImm) {super(initReale.length,initReale[0].length);for (int i = 0; i < righe; i++)

for (int j = 0; j < colonne; j++)data[i][j] = new Complex(initReale[i][j],initImm[i][j]);

}

public Complex addElement(Integer intI, Integer intJ, Complex x){int i = intI.intValue();int j = intJ.intValue();

return ((Complex)data[i][j]).add(x);}

public Complex addElement(Integer intI, Integer intJ, Double x){int i = intI.intValue();int j = intJ.intValue();

return new Complex(((Complex)data[i][j]).parteReale()+x.doubleValue(),((Complex)data[i][j]).parteImmaginaria());

}

public Complex addElement(Integer intI, Integer intJ, Integer x){int i = intI.intValue();int j = intJ.intValue();

return new Complex(((Complex)data[i][j]).parteReale()+x.intValue(),((Complex)data[i][j]).parteImmaginaria());

}

}

Il programmaprincipaledellaclasseMatrix producela seguente uscita:

mat1 = [[1,0,0][0,1,0][0,0,1]]

40 4. Autoreferenzialita

mat2 = [[1.2,-0.75,1.8][-0.99,3.45,-4.89][-9.8,0.08,1.98]]mat3 = [[1.2+i1.2,-0.75+i-0.75,1.8+i1.8][-0.99+i-0.99,3.45+i3.45,-4.89+i-4.89][-9.8+i-9.8,0.08+i0.08,1.98+i1.98]]mat1 + mat1 = [[2,0,0][0,2,0][0,0,2]]mat2 + mat2 = [[2.4,-1.5,3.6][-1.98,6.9,-9.78][-19.6,0.16,3.96]]mat1 + mat2 = [[2.2,-0.75,1.8][-0.99,4.45,-4.89][-9.8,0.08,2.98]]mat1 + mat3 = [[2.2+i1.2,-0.75+i-0.75,1.8+i1.8][-0.99+i-0.99,4.45+i3.45,-4.89+i-4.89][-9.8+i-9.8,0.08+i0.08,2.98+i1.98]]mat3 + mat2 = [[2.4+i1.2,-1.5+i-0.75,3.6+i1.8][-1.98+i-0.99,6.9+i3.45,-9.78+i-4.89][-19.6+i-9.8,0.16+i0.08,3.96+i1.98]]

4.2 Calcolo tempodi esecuzione

In questoesempiosi mostracomeepossibilechiamare il metodomain di unaclassequalunque,nondefinitaal tempodi compilazione,percalcolarneil tempodi esecuzione.

Listato 4.5- Bench.java - tempo di esecuzionedi un metodomain.

import java.lang.reflect.*;

/*** attivazione del metodo main di una classe.** @author P.Bison Copyright 1997*/

public class Bench{

/*** programma principale. Esempio di attivazione di un metodo di una classe* il cui nome e’ dato in una stringa. L’esempio calcola il tempo* di esecuzione in millisecondi del metodo main eventualmente presente* nella classe specificata. Se vi sono argomenti, il primo viene preso* come il nome della classe, mentre i rimanenti sono passati al main di tale* classe. Se non vi sono argomenti si usa la classe Test.*/

public static void main(String[] args) {String classname="Test";Class testclass;Method mainmethod;Class partypes[]= new Class[1];Object mainparlist[] = new Object[1];String[] mainargs = new String[0];long t1,t0;int i;

// eventuale primo argomento e’ il nome della classe// il cui main deve essere eseguitoif (args.length > 0) classname = args[0];

// ottieni un oggetto rappresentate tale classetry {testclass= Class.forName(classname);} catch (ClassNotFoundException excrptRef) {System.out.println("Classe "+classname+" non trovata!");

return;}

// ottieni la classe corrispondente al parametro argspartypes[0]= args.getClass();

// ottieni il metodo main per la data classe// se non esiste viene segnalato un errore ed il programma// terminatry {mainmethod= testclass.getMethod("main",partypes);} catch (NoSuchMethodException excrptRef) {

4. Autoreferenzialita 41

System.out.println("Metodo main non trovato!");return;}

// se vi sono argomenti crea una nuova lista di argomenti// eliminando il primo (nome della classe)

if (args.length > 1) {mainargs = new String[args.length-1];for (i=0;i<args.length-1;i++) mainargs[i]=args[i+1];}

mainparlist[0]=mainargs;t0 = System.currentTimeMillis();

// esegui il metodo main// segnala errore in caso in cui non venga eseguito per// qualche motivotry {mainmethod.invoke(null,mainparlist);} catch (IllegalAccessException excrptRef) {System.out.println("Accesso illegale!");

return;}

catch (IllegalArgumentException excrptRef) {System.out.println("Argomenti illegali!");

return;}

catch (InvocationTargetException exRef) {System.out.print("Eccezione dal main: ");System.out.println(exRef.getTargetException().toString());

return;}

// calcola il tempot1 = System.currentTimeMillis();System.out.println("Time: " + (t1 - t0) + " millisec.");System.out.println();

}

} // end of class Bench

Listato 4.6- Test.java - classedi testper il programma Bench.

public class Test {

public static void main(String[] args) {

System.out.println("Test main");}}

42 4. Autoreferenzialita

Capitolo 5

Programmi nativi

Il linguaggioJava forniscedelle funzionalita per interfacciareprogrammiscritti in Java conprocedurescrittein altrilinguaggi, principalmenteC e C++. Un programmaJava puo quindi attivareprocedurescrittein un altro linguaggioedattraversounbendefinitometodo di interfaccia scambiare informazioni conessevia parametri e/ovalori di ritorno.Ovviamentequestafunzionalita fa perdere il vantaggio della portabilit a poiche il programmapuo essereeseguitosolamentesullamacchina percui e statocompilatoil codicenativo.

Inoltre e possibileper un programmascritto in C o C++attivareunamacchina virtuale Java ed eseguire routinescrittein Java.

5.1 Stampamessaggio

Qualeprimoesempiodi programmanativo si illustraunprogrammachestampaunmessaggioallaconsole.Il programmae costituitodatre file. Il primo definiscela classeSciavoVostro chedichiaraun metodo nativo

ed attraversoun segmentodi codicechevieneeseguito al caricamentodella classecaricala libreria checontiene ilcodicenativo. La dichiarazionee caratterizzatadall presenzadellaparola chiavenative e dal affto chenonvi sonoistruzioniassociateal metodo (assenzadel blocco oqp ).

Listato 5.1- SciavoVostro.java - definizionedi un metodonativo.

/*** implementa la classe SciavoVostro che definisce il metodo nativo** @author P.Bison Copyright 1997*/

public class SciavoVostro{

public static native void nativeSciavoVostro();

// static initializerstatic {System.loadLibrary("sciavo"); // load the shared library libsciavo.so (Solaris)}}

Il secondoprogramma(listato5.1.2) definisceunaclasseil cui mainattiva il metodonativo in tre modi possibili.Dal puntodi vista dell’efficienza,il terzometodoe quello migliore perche non allocamemoria per un oggetto chevieneutilizzatosolamenteperattivare il metodo.

Listato 5.2- Prog.java - attivazionedi un metdonativo.

/*** esempio di classe che attiva un metodo nativo in tre modi differenti** @author P.Bison Copyright 1997

44 5. Programmi nativi.

*/public class Prog{

/*** programma principale*/

public static void main(String[] args){

// varie possibilita’ di invocazione del metodo nativo

// assegnazione di un oggetto della classe SciavoVostro ad una variabile che//poi viene utilizzata per attivare il metodo nativoSciavoVostro sciao = new SciavoVostro();sciao.nativeSciavoVostro();

//creazione di un oggetto senza assegnazione ad una variabile ed invocazione del metodo nativonew SciavoVostro().nativeSciavoVostro(); // istanzia un oggetto della classe SciavoVostro

// e invoca il metodo nativeSciavoVostro

// attivazione del metodo attraverso la classe stessa.// In questo caso il metodo deve essere dichiarato static

SciavoVostro.nativeSciavoVostro();

}}

Infine il terzofile (listato5.1.3) contieneil codicein C delmetodonativo. L’intestazionedellaproceduraassociataal metodoe standardizzataedeveessereconformeallaseguentestruttura:

� il tipo delvaloredi ritorno deve essereJNIEXPORT void JNICALL

� il nomedellaproceduraecreatocomeconcatenazionedi Java seguitodalnomedellaclassein cui edichiaratoil metodoconaggiuntounsottolineato( ), seguitadal nome delmetodo.In questocasoJava SciavoVostro nativeSciavoVostro

� i parametri dellaproceduradevono essereJNIEnv *env, jobject obj

Inoltre si devono includereil file jni.h, chevienefornito dal compilatore Java, e il file SciavoVostro.h, chevienegeneratodaunapposito programmapartendo dalfile SciavoVostro.java.

Listato 5.3- nativeSciavoVostro.c - codicenativo del metodo

#include <jni.h>#include "SciavoVostro.h"#include <stdio.h>

JNIEXPORT void JNICALLJava_SciavoVostro_nativeSciavoVostro(JNIEnv *env, jobject obj){printf("Sciavo vostro!\n");return;

}

datiquestitrefile, i passichesi devono seguirepergenerare il programmaeseguibilesonoi seguenti:

1. compilazionedei dueprogrammiin java:

javac SciavoVostro.java

5. Programminativi. 45

javac Prog.java

2. creazionedel file SciavoVostro.hconil comando

javah -jni SciavoVostro

3. creazionedellasharedlibrary libsciavo.soin Solariscol comando

gcc -G -I r7sutwv�x�y7zA{}|U~a����� JDK/include/solaris nativeSciavoVostro.c -olibsciavo.so

A questopuntoe possibileattivareedeseguireil programmaconil comando

java Prog

5.2 Sommaed inversionedi un array

Listato 5.4- SumArray.java - classeper la definizionedel metodonativo.

/*** implementa la classe SumArray che definisce un metodo* nativo per la somma degli elementi di un vettore di tipo float* @author P.Bison Copyright 1998*/

public class SumArray{

public static native float sumarray (float[]arg);

// static initializerstatic{System.loadLibrary ("sumarray"); // load the shared library libsumarray.so (Solaris)

}}

Listato 5.5- sumarray.c - implementazionein C del metodo.

#include <jni.h>#include "SumArray.h"

/*metodo nativo che calcola la somma di un array di tipo float ecapovolge l’ordine degli elementi dell’array stesso

*/

JNIEXPORT jfloat JNICALLJava_SumArray_sumarray (JNIEnv * env, jobject obj, jfloatArray arr){

jsize len = (*env)->GetArrayLength (env, arr); // calcola dimensione dell’array

int i;float sum = 0.0f;float temp;

// ottieni puntatore all’array (eventuale copia o blocco in memoria)jfloat *body = (*env)->GetFloatArrayElements (env, arr, 0);

// capovolgi i valori dell’arrayfor (i = 0; i < len / 2; i++)

{temp = body[i];body[i] = body[len - 1 - i];body[len - 1 - i] = temp;

}

// calcola somma dei valorifor (i = 0; i < len; i++)

sum += body[i];

// rilascia l’uso dell’array (eventuale copia nel array originale o sblocco della memoria)(*env)->ReleaseFloatArrayElements (env, arr, body, 0);

return sum; // ritorna la somma calcolata

}

Listato 5.6- Prog.java - programma di prova.

/*** classe che attiva un metodo nativo** @author P.Bison Copyright 1997*/

public class Prog{

/*** programma principale*/public static void main (String[]args){

int i;float[] arr1 = new float[12];float ris;

for (i = 0; i < arr1.length; i++){arr1[i] = (float) (i * 10.0);System.out.print (arr1[i] + " ");

}System.out.println ();

// attivazione metodo nativoris = SumArray.sumarray (arr1);

for (i = 0; i < arr1.length; i++){System.out.print (arr1[i] + " ");

}System.out.println ();System.out.println (ris);

}}

Indice dei listati

GUIWindow.java: elementidelAWT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2PrintTest.java: esempiodi stampa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6TextEditor.java: uneditore di testi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Loops.java: cicli infiniti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13TimedLoop.java: cicli temporizzati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

ServerIntf.java: definizione deiserizi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Datum.java: definizioneinformazionescambiata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Server.java: il programmaserver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17Client.java: il programma client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19RobotNameServiceIntf.java: servizidelRobotNameService . . . . . . . . . . . . . . . . . . . . . . . . . 21RobotNameService.java: il programmaperil RobotNameService . . . . . . . . . . . . . . . . . . . . . . 22RobotIntf.java: i comandi del robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23RobotState.java: lo statodel robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24Robot.java: il programma robot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25RemoteCnt.java:il controllo remoto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27InfoIntf.java: interfaccia perricevere l’info rmazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30InfoDeliveryServiceIntf.java: interfacciaperil server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31InfoDeliveryService.java: il programmaserver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31InfoUser.java: programmaclientedel InfoDeliveryService . . . . . . . . . . . . . . . . . . . . . . . . . . 33

Matrix.java - superclassdellematrici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35MatrixInt.java - matrici conelementiinteri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37MatrixDouble.java - matrici conelementireali . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38MatrixComplex.java - matrici conelementicomplessi. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39Bench.java - tempodi esecuzione di unmetodo main. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40Test.java - classedi testperil programmaBench. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

SciavoVostro.java - definizione di unmetodo nativo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43Prog.java - attivazione di unmetdonativo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43nativeSciavoVostro.c- codicenativo delmetodo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44SumArray.java- classeperla definizione delmetodo nativo. . . . . . . . . . . . . . . . . . . . . . . . . . 45sumarray.c - implementazionein C delmetodo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45Prog.java - programmadi prova. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

47