aboutsummaryrefslogtreecommitdiff
path: root/doc/ivy-java.sgml
blob: 310a73302479fb916a15f01ab6f427df35e51643 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
<!--
	The Ivy java guide

	Copyright (c) 1999-2000
	Centre d'Etudes de la Navigation Aerienne

	SGML source file

	Authors: Yannick Jestin <jestin@cena.fr>

-->

<?XML VERSION='1.0' ?>
<!DOCTYPE ARTICLE PUBLIC "-//OASIS//DTD DocBook V3.1//EN">

<article>

<artheader>

<copyright>
<year>2000</year>
<holder>CENA, Centre d'Etudes de la Navigation Aérienne</holder>
</copyright>

<title>The Ivy C++ and java library guide</title>
<subtitle>CENA NT02-819</subtitle>
<titleabbrev>NT02-819 © CENA</titleabbrev>

<authorgroup>
<author>
<firstname>Yannick</firstname><surname>Jestin</surname>
<affiliation><address><email>jestin@cena.fr</email></address></affiliation>
</author>
</authorgroup>
<date>August 4, 2000</date>

<copyright>
<year>2000</year>
<holder>Centre d'Études de la Navigation Aérienne</holder>
</copyright>

<abstract>
<para>
This document is a programmer's guide that describes how to use the Ivy
Java library to connect applications to an Ivy bus. This guide describes
version 1.2 of the library. This document itself is part of the java
package, available on the <ulink
url="http://www.tls.cena.fr/products/ivy/">Ivy web site</ulink>.
</para>
</abstract>
</artheader>

<sect1><title>Foreword</title>

<para>
This document was written in SGML according to the DocBook DtD, so
as to be able to generate PDF and html output. However, the authors
have not yet mastered the intricacies of SGML, the DocBook DtD, the
DocBook Stylesheets and the related tools, which have achieved the
glorious feat of being far more complex than LaTeX and Microsoft Word
combined together. This explains why this document, in addition to being
incomplete, is so ugly. We'll try and improve it. 
</para>

<para>
The Windows ivy-c++ port has been written with the same API. Most of the
documentation for the Ivy java library applies to the windows c++ library.
There is a section dedicated to the description of the intrinsics. There is
also a unix port of this library, which is a C++ wrapper on top of the C
library. There is also a section dedicated to this port.
</para>
</sect1>


<sect1><title>What is Ivy?</title>

<para>
Ivy is a software bus designed at <ulink url="http://www.cena.fr/">CENA</ulink> (France). A software bus is a system 
that allows software applications to exchange information with the illusion of
broadcasting that information, selection being performed by the receiving
applications. Using a software bus is very similar to dealing with events in a
graphical toolkit: on one side, messages are emitted without caring about who
will handle them, and on the other side, one decide to handle the messages that
have a certain type or follow a certain pattern. Software buses are mainly aimed 
at facilitating the rapid development of new agents, and at managing a dynamic
collection of agents on the bus: agents show up, emit messages and receive some, 
then leave the bus without blocking the others.
</para>

<para>
Ivy is implemented as a collection of libaries for several languages and
platforms. If you want to read more about the principles Ivy before reading
this guide of the java 
library, please refer to <citetitle>The Ivy sofware bus: a white
paper</citetitle>. If you want more details about the internals of Ivy, have a
look at <citetitle>The Ivy architecture and protocol</citetitle>. And finally,
if you are more interested in other languages, refer to other guides such as
<citetitle>The Ivy Perl library guide</citetitle>, or <citetitle>The Ivy C library guide</citetitle>. All those documents should be 
available from <ulink url="http://www.tls.cena.fr/products/ivy/">the Ivy Web site </ulink>.
</para>
</sect1>

<sect1><title>The Ivy java library</title>

<sect2><title>What is it?</title>
<para>
The Ivy java library (aka ivy-java or fr.dgac.ivy) is a java package that
allows you to connect applications to an Ivy bus. You can use it to write
applications in java. You can also use it to integrate any thread-safe java
application. So far, this library has been tested and used on a variety of
java virtual machines (from 1.1.8 to 1.4.0), and on a variety of architectures
(GNU/Linux, Solaris, Windows NT,XP,2000, MacOSX).
</para>

<para>
The Ivy C library was originally developed by François-Régis Colin and then
by Yannick Jestin at CENA. It is maintained by a group at CENA (Toulouse, France)
</para>
</sect2>

<sect2><title>Getting and installing the Ivy Java library</title>

<para>
You can get the latest versions of the Ivy C library from <ulink
URL="http://www.tls.cena.fr/products/ivy/">the Ivy web site</ulink>. It is
packaged either as a jar file or as a debian package. We plan to package it
according to different distribution formats, such as .msi (Windows) or .rpm
(Redhat and Mandrake linux). 
</para>

<para>
The package is mainly distributed as a JAR file. In order to use it, either add
it in your CLASSPATH, or put the jar in your $JAVA_HOME/jre/lib/ext/
directory, if you use a java 2 virtual machine. If running windows, be sure to
add it to the right place for runtime (C:\Program Files\JavaSoft\...). The package contains the documentation, the sources and the class files for the fr.dgac.ivy package.
</para>

<para>
In order to test the presence of Ivy on your system once installed, run the following command: 
<screen>
$ <userinput>java fr.dgac.ivy.Probe</userinput>
</screen>
If it spawns a line about broadcasting on a strange address, this is OK, it is
ready and working. If it complains about a missing class (
java.lang.NoClassDefFoundError ), then you have not pointed your virtual
machine to the jar file.
</para>

</sect2>

</sect1>

<sect1><title>Your first Ivy application</title>

<para>
We are going to write a "Hello world translater" for an Ivy bus. The application will subscribe to all messages starting with "Hello", and re-emit them after
translating "Hello" into "Bonjour". In addition, the application will quit when
it receives any message containing exactly "Bye".
</para>

<sect2><title>The code</title>
<para>
Here is the code of "ivyTranslater.java":

<programlisting>
import fr.dgac.ivy.* ;

class ivyTranslater implements IvyMessageListener {

  private Ivy bus;

  ivyTranslater() {
    // initialization
    bus = new Ivy("IvyTranslater","Hello le monde",null);
    bus.bindMsg("^Hello(.*)",this);
    bus.bindMsg("^Bye$",new IvyMessageListener() {
      // callback for "Bye" message
      public void receive(IvyClient client, String[] args) {System.exit(0);}
    });
    try {
       // starts the bus on the default domain or IVY_DOMAIN property
       bus.start(null);
    } catch (IvyException ie) {
      System.err.println("can't run the Ivy bus" + ie.getMessage());
    }
  }

  // callback associated to the "Hello" messages"
  public void receive(IvyClient client, String[] args) {
    bus.sendMsg("Bonjour"+((args.length&gt;0)?args[0]:""));
  }

  public static void main(String args[]) { new ivyTranslater(); }
}
</programlisting>
</para>

</sect2>

<sect2><title>Compiling it</title>
<para>
You should be able to compile the application with the
following command (if the ivy-java jar is in your development classpath):
<screen>
$ <userinput>javac ivyTranslater.java</userinput>
$
</screen>
</para>
</sect2>


<sect2><title>Testing</title>
<para>
We are going to test our application with <command>fr.dgac.ivy.Probe</command>. In a terminal window, launch <command>ivyTranslater</command>.
<screen>
$ <userinput>java ivyTranslater</userinput>

</screen>

Then in another terminal window, launch <command>java fr.dgac.ivy.Probe '(.*)'</command>. You are then ready to start. Type "Hello Paul", and you should get "Bonjour Paul". Type "Bye", and your application should quit:
<screen>
$ <userinput>java fr.dgac.ivy.Probe '(.*)'</userinput>
you want to subscribe to (.*)
broadcasting on 127.255.255.255:2010
IvyTranslater connected
IvyTranslater subscribes to ^Bye$
IvyTranslater subscribes to ^Hello(.*)
IvyTranslater sent 'Hello le monde'
<userinput>Hello Paul</userinput>
-&gt; Sent to 1 peers
IvyTranslater sent 'Bonjour Paul'
<userinput>Bye</userinput>
-&gt; Sent to 1 peers
IvyTranslater disconnected
<userinput>&lt;Ctrl-D&gt;</userinput>
$
</screen>

</para>
</sect2>
</sect1>

<sect1><title>Basic functions</title>

<sect2><title>Initialization and Ivy threads</title>

<para>
Initializing a java Ivy agent is a two step process. First of all, you must
create an <function>fr.dgac.ivy.Ivy</function> object. Once this object is
created, you can add subscriptions to Ivy events, be it messaged, arrival or
departure of other agents, etc, but your agent is still not connected. In
order to connect, you should call the <function>start()</function> method on
your Ivy object. This will run two threads that will remain active until you
call the <function>stop()</function> method on your Ivy object. Once the
<function>start()</function> method has been called, your agent is ready to handle messages on the bus !
</para>

<para>
Here are more details on those functions:

<programlisting>
  fr.dgac.ivy.Ivy(String name,String message, IvyApplicationListener appcb)
</programlisting>
This constructor readies the structures for the software bus connexion. It is
possible to have different busses at the same time in an application, be it on
the same bus or on different ivy busses. The <parameter>name</parameter> is
the name of the application on the bus, and will by transmitted to other
application, and possibly be used by them. The <parameter>message</parameter>
is the first message that will be sent to other applications, with a slightly
different broadcasting scheme than the normal one ( see <citetitle>The Ivy
architecture and procotol</citetitle> document for more information). If
<parameter>message</parameter> is null, nothing will be sent.
<parameter>appcb</parameter>, if non null, is an object implementing the IvyApplicationListener interface. Its different methods will be called upon arrival or departure of an agent on the bus, when your application itself will leave the bus, or when a direct message will be sent to your application.

<programlisting>
public void start(String domainbus) throws IvyException
</programlisting>
This method connects the Ivy bus to a domain or list of domains.
<parameter>domainbus</parameter> is a string of the form 10.0.0:1234, it is
similar to the netmask without the trailing .255. This will determine the
meeting point of the different applications. Right now, this is done with an
UDP broadcast. Beware of routing problems ! You can also use a comma separated
list of domains, for instance "10.0.0.1234,192.168:3456". If the domain is
<parameter>null</parameter>, the API will check for the property
<parameter>IVY_DOMAIN</parameter>, if not present, it will use the default bus, which is 127.255.255.255:2010, and requires a loopback interface to be active on your system. This method will spawn two threads, one listening to broadcasts from other agents, and one listening on the service UDP socket, where remote agent will come and connect. If an IvyException is thrown, your application is not able to talk to the domain bus.

<programlisting>
public void stop() 
</programlisting>
This methods stops the threads, closes the sockets and performs some clean-up.
You can reconnect to the bus by calling <function>start()</function> once again.

</para>
</sect2>

<sect2><title>Emitting messages</title>

<para>
Emitting a message is much like writing a string on a output stream. The
message will be sent if you are connected to the bus and somebody is
interested in its content.

<programlisting>
public int sendMsg(String message) 
</programlisting>
Will send each remote agent the substring in case there is a regexp matching.
The int result is the number of messages actually sent. The main issue here is
that the sender ivy agent is the one who takes care of the regexp matching, so
that only useful information are conveyed on the network.

</para>
</sect2>

<sect2><title>Subscribing to messages</title>

<para>
Subscribing to messages consists in binding a callback function to a message pattern. Patterns are described by regular expressions with captures. When a message matching the regular expression is detected on the bus, the callback function is called. The captures (ie the bits of the message that match the parts of regular expression delimited by brackets) are passed to the callback function much like options are passed to main. Use the <function>bindMsg()</function> method to bind a callback to a pattern, and the <function>unbindMsg</function> method to delete the binding.  

<programlisting>
public int bindMsg(String regex, IvyMessageListener callback);
public void unBindMsg(int id);
</programlisting>
The <parameter>regex</parameter> follows the gnu.regexp regular expression
syntax.  Grouping is done with parenthesis. The <parameter>callback</parameter> is an object implementing the IvyMessageListener interface, with the <function>receive</function> method. The thread listening on the connexion with the sending agent will execute the callback.

</para>
</sect2>
</sect1>


<sect1><title>Advanced functions</title>

<sect2><title>fr.dgac.ivy.Probe utility</title>

<para>
fr.dgac.ivy.Probe is your swiss army knife as an Ivy java developper. Use it
to try your regular expressions, to check the installation of the system, to
log the messages, etc. 
</para>

<para>
The command line options ( available with the --help switch ) are the
following:
<itemizedlist>
<listitem><para>
-b allows you to specify the ivy bus. This overrides the -DIVY_BUS
java property. The default value is 127.255.255.255:2010.
</para></listitem>
<listitem><para>
-n NAME allows you to specify the name of this probe agent on the bus. It
defaults to JPROBE, but it might be difficult to differenciate which jprobe
sent which message with a handful of agents with the same name
</para></listitem>
<listitem><para>
-q allows you to spawn a silent jprobe, with no terminal output.
</para></listitem>
<listitem><para>
-d allows you to use JPROBE on debug mode. It is the same as setting the
VY_DEBUG property ( java -DIVY_DEBUG fr.dgac.ivy.Probe is the same as java
fr.dgac.ivy.Probe -d )
</para></listitem>
<listitem><para>
-h dumps the command line options help.
</para></listitem>
</itemizedlist>
</para>

<para>
The run time commands are preceded by a single dot (.) at the beginning of the
line. Issue ".help" at the prompt ( without the double quotes ) to have the
list of availables comands. If the lines does not begin with a dot, jprobe tries
to send the message to the other agents, if their subscriptions allows it. The
dot commands are the following
<itemizedlist>
<listitem><para>
.die CLIENTNAME issues an ivy die command, presumably forcing the first agent
with this name to leave the bus
</para></listitem>
<listitem><para>
.bye (or .quit) forces the JPROBE application to exit. This is the same as issing an end of file character on a single input line ( ^D ).
</para></listitem>
<listitem><para>
.list gives the list of clients seen on the ivy bus
</para></listitem>
<listitem><para>
.ping issues a ping request. This is only available for ivy java clients so
far, and allows you to try and send a packet to a remote agent, in order to
check the connectivity.
</para></listitem>
</itemizedlist>
</para>
</sect2>

<sect2><title>Direct messages</title>
<para>
Direct messages is an ivy feature allowing the exchange of information between
two ivy clients. It overrides the subscription mechanism, making the exchange
faster ( there is no regexp matching, etc ). However, this features breaks the
software bus metaphor, and should be replaced with the relevant bounded
regexps, at the cost of a small CPU overhead. So far, the sending of direct
message is not available from java, but the receiving is available in the
fr.dgac.Ivy class.
</para>
</sect2>

</sect1>

<sect1><title>Ivy c++ Windows port</title>
<para>
The API is very similiar to the java port, that's why we include this little
section within the ivy java documentation. The author is not familiar with
windows programming or C++ programming so that this documentation might be
inaccurate. Here is a sample listing that might be useful:
</para>

<programlisting>
// ivytest.cpp : Defines the entry point for the console application.
#include &lt;iostream.h&gt;

#include &lt;stdlib.h>

#include "ivy.h"
#include "IvyApplication.h"

static bool TheGrassIsGreenAndTheWindBlows = true;

class cIvyTranslater : public IvyApplicationCallback 
{   
public:
    cIvyTranslater(void);
protected:
	void OnApplicationConnected   ( IvyApplication *app );
	void OnApplicationDisconnected( IvyApplication *app );
	void HelloCallback  ( IvyApplication *app, int argc, const char **argv );
	void ByeCallback    ( IvyApplication *app, int argc, const char **argv );
	Ivy *bus;
};



cIvyTranslater::cIvyTranslater(void) 
{
    // initialization
	bus = new Ivy( "cIvyTranslater","cIvyTranslater READY",this,FALSE);

    int count;
    count = bus-&gt;BindMsg( "^Hello(.*)", BUS_CALLBACK_OF(cIvyTranslater, HelloCallback ));
    count = bus-&gt;BindMsg( "^Bye$",      BUS_CALLBACK_OF(cIvyTranslater, ByeCallback ));
    
    bus-&gt;start("127.255.255.255:2010");
}

void cIvyTranslater::HelloCallback(IvyApplication *app, int argc, const char **argv)
{
    const char* arg = (argc &lt; 1) ? "" : argv[0];
	cout &lt;&lt; "cIvyTranslater received msg: Hello'" &lt;&lt; arg
	&lt;&lt; "'" &lt;&lt; endl;
    bus-&gt;SendMsg( "Bonjour%s!", arg );
}

void cIvyTranslater::ByeCallback(IvyApplication *app, int argc, const char **argv)
{
	cout &lt;&lt; "cIvyTranslater stops bus" &lt;&lt; endl;
    if (bus) {
        TheGrassIsGreenAndTheWindBlows = false;
        bus-&gt;stop(); 
        delete bus; // This statement is never reached! Don't know why!
    }
	
}

void cIvyTranslater::OnApplicationConnected(IvyApplication *app)
{
	cout &lt;&lt; "cIvyTranslater is ready to accept messages from "
	&lt;&lt; app-&gt;GetName() &lt;&lt; endl;
}

void cIvyTranslater::OnApplicationDisconnected(IvyApplication *app)
{
	cout &lt;&lt; "cIvyTranslater good buy '" &lt;&lt; app-&gt;GetName()
	&lt;&lt; "'" &lt;&lt; endl;
}


void main(int argc, char* argv[]) 
{
    cIvyTranslater aIvyTL;

    while (TheGrassIsGreenAndTheWindBlows) {
        Sleep(2000);
        cout &lt;&lt; "new cycle..." &lt;&lt; endl;
    }
	cout &lt;&lt; "Good buy, world\n";
}
</programlisting>

<sect2><title>Win32 API</title>
<para>
</para>
</sect2>

<sect1>
<title>programmer's style guide</title>
<para>
[to be written]
</para>
</sect1>

<sect1>
<title>Contacting the authors</title>
<para>
The Ivy java library is now maintained by Yannick Jestin. For bug reports or
comments on the library itself or about this document, please send him an
email at <email>jestin@cena.fr</email>. For comments and ideas about Ivy itself
(protocol, applications, etc), please join and use the Ivy mailing list:
<email>ivy@tls.cena.fr</email>. 
</para>
</sect1>

</article>