/usr/share/gtk-doc/html/libbonobo/monikers-overview.html is in libbonobo2-dev 2.32.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 | <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Monikers in the Bonobo Component System</title>
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="index.html" title="Libbonobo Reference Manual">
<link rel="up" href="monikers.html" title="Monikers">
<link rel="prev" href="monikers.html" title="Monikers">
<link rel="next" href="libbonobo-bonobo-moniker.html" title="BonoboMoniker">
<meta name="generator" content="GTK-Doc V1.16 (XML mode)">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="2"><tr valign="middle">
<td><a accesskey="p" href="monikers.html"><img src="left.png" width="24" height="24" border="0" alt="Prev"></a></td>
<td><a accesskey="u" href="monikers.html"><img src="up.png" width="24" height="24" border="0" alt="Up"></a></td>
<td><a accesskey="h" href="index.html"><img src="home.png" width="24" height="24" border="0" alt="Home"></a></td>
<th width="100%" align="center">Libbonobo Reference Manual</th>
<td><a accesskey="n" href="libbonobo-bonobo-moniker.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
</tr></table>
<div class="refentry">
<a name="monikers-overview"></a><div class="titlepage"></div>
<p>Monikers in the Bonobo Component System.</p>
<p>Miguel de Icaza (miguel@ximian.com)</p>
<div class="refsect1">
<a name="id403277"></a><h2>Monikers in the Bonobo Component System</h2>
<div class="refsect2">
<a name="id403283"></a><h3>Introduction</h3>
<p>
We recently reimplemented and fully revamped the the
Moniker support in Bonobo. This work has opened a
wide range of possibilities: from unifying the object
naming space, to provide better integration in the
system. </p>
<p> Note: on this document I have ommited exception
environments handling for the sake of explaining the
technology.</p>
</div>
<hr>
<div class="refsect2">
<a name="id403592"></a><h3>Monikers - a user perspective</h3>
<p>
Monikers are used to name objects, they effectively
implement an object naming space. You can obtain
monikers either because you created the moniker
manually, or from a stringified representation of a
moniker.</p>
<p>Here is a list of stringified monikers, and an
interpretation of it:</p>
<div class="variablelist"><table border="0">
<col align="left" valign="top">
<tbody>
<tr>
<td><p><span class="term"><code class="literal">
file:quake-scores.gnumeric</code></span></p></td>
<td><p>
This would be a moniker that represents the
file <code class="filename">quake-scores.gnumeric</code>
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
oafid:GNOME:Gnumeric:WorkbookFactory:1.0</code></span></p></td>
<td><p>
This moniker represents the Gnumeric Workbook
factory object.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
oafid:GNOME:Gnumeric:WorkbookFactory:1.0:new:
</code></span></p></td>
<td><p>
This moniker represents a Gnumeric Workbook instance.
Notice that we are using the exact same OAFID
as the example before, but there is a "new:"
suffix at the end.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:/tmp/a.gz
</code></span></p></td>
<td><p>
This represents the file
in <code class="filename">/tmp/a.gz</code>.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:/tmp/a.gz#gunzip
</code></span></p></td>
<td><p>
This represents the decompressed stream of
data from <code class="filename">a.gz</code>.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:/tmp/a.gz#gunzip:streamcache
</code></span></p></td>
<td><p>
This provides a cache on top of the
decompressed stream of data
for <code class="filename">a.gz</code> (the streamcache
moniker is an in-proc component).
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
http://www.gnome.org
</code></span></p></td>
<td><p>
This one represents the GNOME web site.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
evolution:Mail/Inbox
</code></span></p></td>
<td><p>
This represents the Evolution Mail/Inbox
folder.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:quake-scores.gnumeric!January
</code></span></p></td>
<td><p>
This represents the January Sheet in the
<code class="filename">quake-scores.gnumeric</code> workbook.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:quake-scores.gnumeric!January!Winner
</code></span></p></td>
<td><p>
This represents the cell whose name is
"Winner" in the January sheet in the
<code class="filename">quake-scores.gnumeric</code> workbook.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:quake-scores.gnumeric!January!Winner!Style!Font
</code></span></p></td>
<td><p>
This represents the Font interface of the
Style attached to the Winner cell.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:quake-scores.gnumeric!Jannuary!Winner!Style!BackgroundColor
</code></span></p></td>
<td><p>
This represents the background color for the cell.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
http://www.gnome.org/index.html!title
</code></span></p></td>
<td><p>
This represents the title element in the HTML
web page at <code class="literal">www.gnome.org</code>.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:toyota.xml!cars/car/model/
</code></span></p></td>
<td><p>
The "cars/car/model" is an XPath expression
that for locating a specific node in the
<code class="filename">toyota.xml</code> file.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
config:*/Session/Calendar
</code></span></p></td>
<td><p>
This represents a PropertyBag for the GNOME
Calendar using the Local configuration system
and using the settings stored in the Session
domain.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
oafid:Helix:Evolution:Wombat:1.0
</code></span></p></td>
<td><p>
This represents the Evolution model server
that stores all the per-user information.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
queue:oafid:Helix:Evolution:Wombat
</code></span></p></td>
<td><p>
This represents an interface that queues CORBA
requests to the Evoution Wombat: Any calls
issued will be queued: if the Wombat is busy
or not accepting connection, all the CORBA
method invocations will be queued without
stopping the execution of the client code.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
http://www.gnome.org/index.html.gz#gunzip#html:title
</code></span></p></td>
<td><p>
This will reutrn the title element of the
compressed HTML file at
<code class="literal">http://www.gnome.org/index.html.gz</code>
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
ftp://ftp.gnome.org/gnome-core-1.0.tar.gz#utar/gnome-core-1.0/ChangeLog
</code></span></p></td>
<td><p>
A reference to the ChangeLog file contained in
the compressed gnome-core-1.0.tar.gz tar file
at <code class="literal">ftp://ftp.gnome.org</code>.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
desktop:Backgound
</code></span></p></td>
<td><p>
The background object for the user's desktop.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
trashcan:
</code></span></p></td>
<td><p>
The system trashcan.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:logo.png
</code></span></p></td>
<td><p>
This represents the logo.png file.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
oafid:OAFIID:eog_viewer_factory:file:logo.png
</code></span></p></td>
<td><p>
This specifies a specific image viewer to be
used to display the file "<code class="literal">logo.png</code>", in this
case the "EOG" program.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:logo.png!Zoom=2.0
</code></span></p></td>
<td><p>
This represents
the <code class="filename">logo.png</code> file in EOG
at zoom level 2.0.
</p></td>
</tr>
<tr>
<td><p><span class="term"><code class="literal">
file:logo.png!Zoom=2.0,dither=max,notransparency
</code></span></p></td>
<td><p>
The image logo.png is configured to be zoomed
at 2.0 factor, to do maximum dithering and not
use any transparency.
</p></td>
</tr>
</tbody>
</table></div>
<p>
Now, what you saw above are some examples of
stringified representations of monikers. This means
that they are not really monikers, it is the way a
Moniker is represented in string form.
</p>
<p>
Monikers typically are created either by using a
Bonobo API call that transforms the stringified
representation into an object (which exports the
<code class="literal">IDL:Bonobo/Moniker:1.0</code> interface),
like this:
</p>
<pre class="programlisting">
moniker = bonobo_moniker_client_new_from_name (moniker_string);
</pre>
<p>
Now, a moniker is only interesting because it can
yield other objects when resolved. During the
resolution process, you specify which interface you
are intersted on the moniker to return. This is
achieved by invoking the ::resolve method on the
moniker and passing the repoid of the interface you
desire, like this:</p>
<pre class="programlisting">
Bonobo::Unknown control;
control = moniker->resolve ("Bonobo/Control")
</pre>
<p> This would request the moniker to return an object
that implements the IDL:Bonobo/Control:1.0 interface.
This means that the object could be embedded as a
regular Bonobo control in applications.</p>
<p> Maybe you do not want to get a control, but rather
to resolve the moniker against a different interface,
for instance a Bonobo::PropertyBag interface:</p>
<pre class="programlisting">
properties = moniker->resolve ("Bonobo/PropertyBag");
</pre>
<p>The resolution process might yield completely different
objects.</p>
<p>The parsing and resolution process is all
encapsulated into a single API call for your
convenience: the bonobo_get_object function:</p>
<pre class="programlisting">
Bonobo::Unknown bonobo_object_get (char *moniker_string, char *interface);
</pre>
<p> Now, as I said, the resolution process might yield
very different objects depending on the interface
being requested, for example:</p>
<pre class="programlisting">
x = bonobo_object_get ("http://www.gnome.org", "Bonobo/Control")
y = bonobo_object_get ("http://www.gnome.org", "Bonobo/Stream")
</pre>
<p>The "x" object might launch Mozilla which would in turn load
<code class="literal">www.gnome.org</code>, and the returned
object can be used as a Bonobo Control, and used in
your application as a widget.</p>
<p> The "y" object on the other hand does not need all
the power of Mozilla, we are only requesting the very
simple Stream interface, so we might be able to
implement this with a lightweight HTTP implementation:
maybe a wget-based bonobo server, or a libghttp
server. </p>
<p> Note that even if the stringified versions of the
monikers were the same (ie, "http://www.gnome.org")
the resulting objects might differ wildely depending
on the interface being requested. </p>
</div>
<hr>
<div class="refsect2">
<a name="id404220"></a><h3>The Moniker parsing system</h3>
<p>During parsing the Moniker stringified, Bonobo will
use the colon-terminated prefix as the toplevel
moniker to be invoked for the resolution process.</p>
<p>For the prefix "file:" the file moniker will be used; For the
prefix "oafid", the oafid moniker will be used; For the
"queue:" prefix, the queue moniker will be used.</p>
<p>Once the moniker that handles a specific prefix has
been activated, the moniker will be requested to parse
the remaining of the string specification and return a
valid moniker.</p>
<p>Each moniker typically will consume a number of
bytes up to the point where its domain stops, will
figure out what is the next moniker afterwards. Then
it will activate the next moniker and pass the
remaining of the moniker stringified version until the
parsing is finished.</p>
<p>Each moniker is free to define its own mechanism for parsing,
its special characters that are used to indicate the end of a
moniker space, and the beginning of a new one (like the "#"
and the "!" characters in some of the examples above). This
flexibility is possible because each moniker gets to define
its rules (and this is important, as we want to integrate with
standards like http and file).</p>
</div>
<hr>
<div class="refsect2">
<a name="id404253"></a><h3>Monikers as an object naming scheme</h3>
<p>As you can see, monikers are used to implement a
naming system that can be used to reference and
manipulate objects. As you might have noticed, the
::resolve method on the Moniker interface returns a
Bonobo::Unknown interface. And by definition, the
bonobo_get_object also returns a Bonobo::Unknown.</p>
<p>This means that the resulting object from the
moniker resolution will always support ref, unref and
query_interface methods.</p>
<p>The Moniker object naming scheme is:</p>
<div class="variablelist"><table border="0">
<col align="left" valign="top">
<tbody>
<tr>
<td><p><span class="term">Extensible</span></p></td>
<td><p> A new entry point into the
object naming space can be created and
installed into the system.</p></td>
</tr>
<tr>
<td><p><span class="term">Hierarchical</span></p></td>
<td><p> Monikers. </p></td>
</tr>
</tbody>
</table></div>
</div>
<hr>
<div class="refsect2">
<a name="id404305"></a><h3>Creating Monikers</h3>
<p>Monikers are created typically by API calls into the
Bonobo runtime or by your own classes that implement
monikers.</p>
</div>
<hr>
<div class="refsect2">
<a name="id404318"></a><h3>Object Name Space</h3>
<div class="refsect3">
<a name="id404322"></a><h4>Comparing the Moniker name space with the
Unix Name Space</h4>
<p> Lets start simple. A moniker is a reference to
an object[1]. To actually use the object, you
have to "resolve" the moniker. The term used in
the literature is "binding the object". </p>
<p> The result of resolving the moniker is a
<code class="literal">Bonobo::Unknown</code> object.</p>
<p>Think of a moniker as a pathname. And think of the
binding process as the "open" system call on Unix.</p>
<p>Example:</p>
<div class="informaltable"><table border="0">
<colgroup>
<col>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td> </td>
<td>Unix Files</td>
<td>Monikers</td>
</tr>
<tr>
<td>Object naming:</td>
<td>path name</td>
<td>moniker string representation</td>
</tr>
<tr>
<td>Binding function:</td>
<td>open(2)</td>
<td>bonobo_get_object</td>
</tr>
<tr>
<td>Return value:</td>
<td>kernel file descriptor</td>
<td>Bonobo::Unknown CORBA reference</td>
</tr>
<tr>
<td>Binder:</td>
<td>Kernel VFS+each FS</td>
<td>bonobo_get_object + Bonobo::Moniker</td>
</tr>
<tr>
<td>Persisting:</td>
<td>none</td>
<td>Moniker::QI(Persist)</td>
</tr>
</tbody>
</table></div>
<p>In the case of the file system, the kernel does
the "resolution" of each path element by parsing
one element of the file system, and the Virtual
File System switch uses the current file system +
mount points to resolve the ultimate file name.</p>
</div>
</div>
<hr>
<div class="refsect2">
<a name="id404464"></a><h3>File Linking</h3>
<p> Monikers were originally implemented as part of the
Microsoft OLE2 compound document system. They can be
used effectively by applications during drag and drop
and cut and paste operations to pass objects that must
be linked by other applications.</p>
<p>The source application would create a moniker for a
given object that would fully identify it, and pass it
through a drag and drop operation or a cut and paste
operation to the recipient application.</p>
<p>The recipient application then can resolve the
moniker against the interface required (in the Bonobo
case, Bonobo/Embeddable, or Bonobo/Control would be a
common choice).</p>
<p>Applications do not need to store the entire
contents of linked information, they can just store a
stringified representation of the moniker, and resolve
it again at load time.</p>
</div>
<hr>
<div class="refsect2">
<a name="id404491"></a><h3>Instance initialization</h3>
<p>Monikers can be used to initialize objects, as a way
of passing arguments to your object. This is coupled
with the Bonobo/ItemContainer interface and the Item
Moniker.</p>
<p>The Item Moniker is covered later.</p>
</div>
<hr>
<div class="refsect2">
<a name="id404505"></a><h3>Resolution of a moniker against an interface</h3>
<p>A moniker can be resolved against different
interfaces. The resulting object might be different
depending on the interface that is being resolved. To
illustrate this, here is an example, lets say we have
the <code class="literal">"http://www.helixcode.com"</code>
string representation of a moniker.</p>
<p>The string representation of the moniker can be resolved
against the "Bonobo/Control" interface:</p>
<pre class="programlisting">
bonobo_get_object ("http://www.helixcode.com", "Bonobo/Control");
</pre>
<p>This could return an embeddable Mozilla component
that is suitable to be embedded into your application
as a widget (because we are requesting the moniker to
return a Bonobo/Control interface). If the interface
is resolved against the "Bonobo/Stream"
interface,maybe Mozilla is not required, and the
process could use a smaller process that just provides
Bonobo/Streams, say a corbaified wget.</p>
<p>The logic for this lives on the http: moniker
handler.</p>
</div>
<hr>
<div class="refsect2">
<a name="id404543"></a><h3>Core monikers</h3>
<p>Bonobo ships with a number of moniker handlers: the
<code class="literal">file</code> moniker,
the <code class="literal">item</code> moniker,
the <code class="literal">oafid</code> moniker and
the <code class="literal">new</code> moniker.</p>
<div class="refsect3">
<a name="id404575"></a><h4>The file moniker</h4>
<p>The file moniker is used to reference files.
For instance:</p>
<pre class="programlisting">file:sales.gnumeric</pre>
<p> The file moniker will scan its argument until
it reaches the special characters `#' or `!' which
indicate the end of the filename.</p>
<p>The file moniker will use the mime type
associated with the file to find a component that
will handle the file. Once the object handler has
been invoked, the Moniker will try to feed the
file to the component first through quering the
PersistFile interface, and if this is not
supported, through the PersistStream interface.</p>
</div>
<div class="refsect3">
<a name="id404602"></a><h4>The item moniker</h4>
<p>The item moniker is typically triggered by the
"!" string in the middle. The item moniker can be
used to implement custom object naming, or
argument handling.</p>
<p>The item moniker parses the text following '!'
until the next '!' character, this is called the
argument of the item moniker. During the
resolution process, the item moniker will request
from its parent the Bonobo/ItemContainer interface
and will invoke the getObject on this interface
with the argument.</p>
<p>For example, in a Gnumeric spreadsheet this
allows programmers to reference sub-objects by
name. For instance, Workbooks can locate Sheet
objects; Sheets can locate range names, cell
names, or cell references.</p>
<p>This moniker would reference the sheet named
`Sales' in the workbook contained in the
sales.gnumeric spreadsheet:</p>
<pre class="programlisting">
sheet = bonobo_get_object ("sales.gnumeric!Sales", "Gnumeric/Sheet");
</pre>
<p>This other would reference the cell that has been named
`Total' inside the Sheet "Sales":</p>
<pre class="programlisting">
cell = bonobo_get_object ("sales.gnumeric!Sales!Total", "Gnumeric/Cell")
</pre>
<p> The way this works from the container
perspective, is that the container will implement
the <code class="function">getObject</code> (string)
method, and would respond to
the <code class="function">getObject</code> request.</p>
<p> Item monikers can also be used to perform
instance initialization. The component that wants
to support instance initialization needs to
support the Bonobo/ItemContainer interface and
implement a getObject method that would return the
object properly initialized.</p>
<p> For example, lets consider an image viewer
component that can be configured, like this: </p>
<pre class="programlisting">
image = bonobo_get_object ("file.jpg!convert_to_gray=on", "Bonobo/Control")
</pre>
<p>The above example would activate the EOG
component because of the file.jpg match, and then
invoke EOG's ItemContainer implementation with the
argument "convert_to_gray=on". getObject should
return an object (which would be itself) but it
would modify the instance data to set the
"convert_to_gray" flag to on. Like this:</p>
<pre class="programlisting">
Bonobo_Unknown
eog_item_container_get_object (BonoboObject *o, char *name)
{
if (command_is (name, "convert_to_gray", &v))
image_set_convert_to_gray (o, v);
...
bonobo_object_ref (o);
return bonobo_objet_corba_objref (o);
}
</pre>
</div>
<div class="refsect3">
<a name="id404691"></a><h4>The oafiid moniker</h4>
<p>The <code class="literal">oafid:</code> moniker handles
activation using the Object Activation Framework.
This allows application programmers to activate
objects by their OAF ID, like this:</p>
<pre class="programlisting">
gnumeric = bonobo_object_get ("oafiid:GNOME_Gnumeric_Workbook", iface)
</pre>
</div>
<div class="refsect3">
<a name="id404714"></a><h4>The "new:" moniker</h4>
<p>The new moniker requests from its parent the
"Bonobo/GenericFactory" interface and invokes the
method create_instance in the interface.</p>
<p>Typically this moniker would be invoked like this:</p>
<pre class="programlisting">
bonobo_get_object ("oafid:RandomFactory:new:", iface);
</pre>
<p>In the example above "RandomFactory" is the
OAFID for the factory for a certain object.
During the resolution process, the "new:" moniker
would request its parent to resolve against the
IDL:GNOME/ObjectFactory:1.0 interface (which is
the traditional factory interface in GNOME for
creating new object instances) and then invoke the
new_instance method on it.</p>
<p>Historically GNORBA (the old GNOME object
activation system) and OAF (the new object
activation system) implemented a special "hack" to
do this same processing. Basically, the
description files for the object activation system
was overloaded, there were three types of
activation mechanism defined:</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>activate object implementation from an
executable.</p></li>
<li class="listitem"><p>activate object implementation from a
shared library.</p></li>
<li class="listitem"><p>activate object implementation by
launching another object, and querying the
launched object for the ObjectFactory
interface.</p></li>
</ul></div>
<p>The "new:" moniker basically obviates the need
for the last step in the activation system. With
OAF, using the OAF approach proves to be more
useful, as it is possible to query OAF for
components that have certain attributes, and the
attributes for a factory object are not as
interesting as the attributes for the instances
themselves. Despite this, the "new:" moniker can
be used for performing the operation of instance
initialization in more complex scenarios that go
beyond the scope of activation provided by
OAF.</p>
</div>
</div>
<hr>
<div class="refsect2">
<a name="id404775"></a><h3>Adding moniker handlers to the system</h3>
<p><b>Ideal monikers: </b>There are two moniker handlers that would be
interesting to implement: the Configuration
Moniker and the VFS moniker.</p>
<p>They both help the system overall, because the added
simplicity of having a standard way of activating
services in the system and given that the API to these
services is CORBA-based, any programming language with
CORBA/Bonobo support can make use of them without the
need of a special language binding.</p>
<p>I am convinced that this helps make the system more
self consistant internally.</p>
<div class="refsect3">
<a name="id404799"></a><h4>The Configuration Moniker</h4>
<p>The configuration moniker is invoked by using
the <code class="literal">"config:"</code> prefix. The
string afterwards is the configuration locator.
The moniker should support being querried against
the "Bonobo/Property" or "Bonobo/PropertyBag"
depending on whether we are requesting a set of
attributes, or a single attribute.</p>
<p>For example, retrieving the configuration
information for a specific configuration property
in Gnumeric would work like this:</p>
<pre class="programlisting">
Bonobo_Property auto_save;
CORBA_Any value;
auto_save = bonobo_get_object (
"config:gnumeric/auto-save", "/Bonobo/Property");
value = bonobo_property_get_value (auto_save, &ev);
if (value-> tc-> kind == CORBA_tk_bool)
printf ("Value: %s\n", (CORBA_bool) value->_value ? "true" : "false");
else
printf ("Property is not boolean\n");
</pre>
<p> In the above example, we first use the
<code class="function">bonobo_get_object</code> routine to locate the
configuration object through its moniker. The
return value from the <code class="function">bonobo_get_object</code> is of type
<code class="literal">Bonobo_Property</code> which is the
standard Bonobo way of manipulating
properties.</p>
<p>This has two main advantages:</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem">
<p>By accessing the configuration engine
through the moniker interface we have
eliminated the need to define a C-specific
API for the configuration management. The
configuration could have been reached
through any other programming language
that supports CORBA.</p>
<p>The GNOME project has always tried to
define APIs that could be easily wrapped
and accessed from various languages
(particularly, we have done this with the
toolkit and recently with the CORBA
bindings).</p>
<p>But even if we have taken special care
of doing this, and there are continous
efforts to wrap the latest and greatest
APIs, widgets, and tools, the bindings
typically lag a few weeks to monthsw
behind the actual C API.</p>
<p>By moving towards CORBA, we only need to
support CORBA in the various programming
languages and we get access to any new
APIs defined by it.</p>
</li>
<li class="listitem"><p>Any tools on the system that can
manipulate a Bonobo::Property or
::PropertyBag (a GUI in a visual designer,
or a configuration engine that
persists/hidrates objects, or a browsing
tool) can talk directly to the
configuration engine all of a sudden, as
we are using the same interface method
across every language on the system.</p></li>
</ul></div>
<p>The Bonobo::Property interface is pretty
comprehensive, and should address most needs, the
methods are:</p>
<pre class="synopsis">
string get_name ();
TypeCode get_type ();
any get_value ();
void set_value ();
any get_default ();
string get_doc_string ();
long get_flags ();
</pre>
<p>Now, this interface as you can see does not
specify an implementation for the actual backend.
Given that this is just an interface, we do not
care what the moniker will connect us to, we only
care with the fact that we will be able to use the
Property and PropertyBag interfaces.</p>
</div>
<div class="refsect3">
<a name="id404915"></a><h4>Configuration transactions</h4>
<p>Handling of transactional changes to the
configuration system can be achieved by the use of
the setValues interface in the PropertyBag. The
implementation of the PropertyBag can either
accept the values set, or it can do consistency
checking of the values being set (for instance, to
avoid the configuration to contradict itself, or
store invalid values). If the values being set
are invalid, an exception is thrown.</p>
<p>It would be also possible to hook up an
arbitrary consistency checking component in the
middle, by inserting the consistency checking in
the middle of the stream, like this:</p>
<pre class="programlisting">
bonobo_get_object ("config:gnumeric/auto-save:gnumeric-consistency-check:", "Bonobo/Property");
</pre>
<p>Notice the `gnumeric-consistency-check:' moniker handler.
This could just be a shared library consistency checking
component if it needs to be.</p>
</div>
<div class="refsect3">
<a name="id404944"></a><h4>Listening to changes.</h4>
<p>
One of the requirements for a modern desktop is to
be react globally when changes are made to global
settings. For example, in the GNOME desktop when
a theme is changed, a special protocol inside Gtk+
is used to notify all the applications that they
should reload their theme configuration.
</p>
<p>There are many other examples where applications
need to keep track of the current setting. For
example, when a preference is changed, we want the
preference to take place right away, without us
having to restart our running applications.
</p>
<p>This is easily achieved by registering a
Listener with the Bonobo/EventSource in the
PropertyBag.</p>
</div>
<div class="refsect3">
<a name="id404965"></a><h4>What about GConf?</h4>
<p>GConf is a configuration management
infrastructure that provides the following
features:</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>A schema system for specifying the
various configuration options, as well as
their documentation and initial values
(default values).</p></li>
<li class="listitem"><p>A way for the system administrator
to override values in a system-wide fashion
(this encompasses a network-wise setup if
desired).</p></li>
<li class="listitem"><p>A change notification system:
applications might be notified of changes to
various values they might want to keep track
of.</p></li>
</ul></div>
<p>There are two drawbacks to GConf currently:</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>Although gconf provides pretty
much everything that is required, but it is a
C-based API that needs to be wrapped for every
language that wants to support GConf.</p></li>
<li class="listitem"><p>GConf is limited in the kind of
information that can be stored on its
database. A BonoboProperty stores a CORBA_Any
which can contain any of the simple CORBA
types (strings, integers, floating points,
booleans), structures, arrays and
unions.</p></li>
</ul></div>
<p>The actual engine and backend for GConf could
become the configuration moniker handler, only the
API would be replaced as well as the actual
storage system to support the more complete
CORBA_Any, and the ad-hoc CORBA interface can be
replaced with a more powerful system.</p>
</div>
<div class="refsect3">
<a name="id405025"></a><h4>Configuration management: Open Issues</h4>
<p><b>Specifying the location for
configuration. </b>The syntax for accessing the configuration
has not been defined, but we can cook this up
pretty easily.</p>
<p>Forcing the configuration data to be loaded from
a specific location. Although the arguments to
the moniker could be used to encode a specific
location, for example:</p>
<pre class="programlisting">
config:~/file.config!auto-save
</pre>
<p> It seems more natural to use the file moniker
to provide this information, for example:</p>
<pre class="programlisting">
file:~/file.config!config:auto-save
</pre>
<p>The config moniker can test for the presence of
a parent, and if the parent exists, then it would
request one of the Persist interfaces from it to
load the actual configuration file, and provide
access to it.
</p>
<p><b>Transactional setting of values. </b>It might make sense to "batch" a number of
changes done under a prefix to avoid listeners
to a range of keys to reset themselves
multiple times. Consider the case in which a
command line tool makes various changes to the
background properties, say the changes are
done in this order:</p>
<pre class="programlisting">
background = bonobo_get_object ("config:desktop/background", "PropertyBag");
bonobo_property_bag_set_values (background,
bonobo_property_list_new (
"gradient", "string", "true",
"color1", "string" "red",
"color2", "string" "blue",
&ev);
</pre>
<p>If the real configuration program for handling
the background is running at that point, it will
have registered to be notified of changes to all
those values. The changes might be very
expensive. For example the code migh react to
every change and recompute the whole background
image on each change.</p>
<p>An optimization would be to tag the beginning of
the transaction and the end of it in the client
code to allow listeners to get batched
notification of changes:</p>
<pre class="programlisting">
background = bonobo_get_object ("config:desktop/background", iface);
bonobo_property_bag_batch_push (background);
bonobo_property_set (background, "gradient", "true");
bonobo_property_set (background, "color1", "red");
bonobo_property_set (background, "color2", "blue");
bonobo_property_bag_batch_pop (background);
</pre>
<p>This would allow the listener code to batch all
the expensive requests into a single pass.</p>
<p><b>Configuration handlers. </b>Consider the example above, we would like to
be able to change properties on the system and
have those properties to take effect
independently of whether a listener is
registered or not.</p>
<p>A property handler might register with the
configuration moniker to be launched when a
property changes. This could be done in a file
installed in a special location.</p>
</div>
<div class="refsect3">
<a name="id405128"></a><h4>The GNOME VFS becomes deprecated.</h4>
<p>The GNOME VFS provides an asyncronouse
file-system interface abstraction that can be used
to access local files, remote files, files in
compressed files and more.</p>
<p>The problem with the GNOME VFS is that it is
very limited: it can only expose a file system
like interface to its clients (very much like the
Unix interface after which it was modeled).</p>
<p> As covered before in the `Object Naming Space',
Monikers define an object naming space, and
monikers can be defined for any type of resource
that the GNOME VFS supports (a transitional path
might include a set of monikers implemented on top
of the actual GNOME VFS).</p>
<p> A file dialog could request a moniker to be
resolved against a "Graphical File Listing"
interface, which might result in a miniature
Nautilus window to be embedded in the dialog
box.</p>
<p>It would be possible to entirely reuse the
existing GNOME VFS code by providing monikers for
the various access methods that would handle the
special cases "Stream", "Storage" and
"FileListing". Other interfaces will be plugged
into the moniker handler to support the richer
content.</p>
<p> For instance, consider the "trashcan:" moniker.
The trashcan moniker could be resolved against
various interfaces. A file manager would resolve
it against a DirectoryListing interface to display
the contents of it; It could resolve it against a
"Control" interface to get a trahscan custom view
(to configure the values in the trashcan); a
PropertyBag interface could be used to
programmatically configure the various settings in
it.</p>
</div>
</div>
<hr>
<div class="refsect2">
<a name="id405169"></a><h3>Other monikers</h3>
<p>There is another family of moniker handlers that are
worth stuyding. The filtering moniker handlers and
the caching moniker handlers.</p>
<div class="refsect3">
<a name="id405178"></a><h4>The <code class="literal">streamcache:</code> moniker</h4>
<p>The idea of the streamcache: moniker is to be
basically a shared library moniker handler that
provides a cache for the IDL:Bonobo/Stream:1.0
interface.</p>
<p>This moniker is very simple, during resolution
it requests the IDL:Bonobo/Stream:1.0 interface
from its parent and it can only expose the
IDL:Bonobo/Stream:1.0 interface to clients.</p>
<p>The plus is this: it is a shared library
component, which will run in the address space of
the application that will use the Stream, and it
provides a cache to the parent Stream (so we can
use small granular method invocations, and the
stream cache can do the traditional buffering).</p>
<p> Think of this difference as the one between an
application using write()/read and the application
using fwrite/fread/getc/putc: although many
applications can implement their own buffering,
most of the time just using the libc-provided ones
(fwrite/fread/getc/putc) will do it. This is
exactly what the streamcache: moniker will do: By
appending this to a stringified representation of
a moniker, you can get a Stream cache for free.</p>
</div>
<div class="refsect3">
<a name="id405213"></a><h4>The #gunzip, #utar filtering monikers</h4>
<p>The #utar moniker is a moniker that would
implement tar file decoding (the same concept can
be used for other archive formats). This moniker
uses an auxiliary tar component handler. The
moniker connects the tar component handler to the
parent object's Stream interface and returns the
resulting object. The result of the #utar moniker
can be either a Bonobo/Stream (for a file
reference) or Bonobo/Storage (for a directory
reference).</p>
<p>Like this:</p>
<pre class="programlisting">
file:/home/miguel/mail-backup.tar#utar:2000/may/1001
ftp://ftp.helixcode.com/pub/sources/gnome-libs-1.2.tar.gz#gunzip#utar:/README
</pre>
<p>The beauty of this system is that if two
applications use the same moniker, they would be
sharing the same data without having to uncompress
two times the same tar file.</p>
<p>This is all achieved transparently. This would
happen in quite a few instances, for example, if
you are exploring a compressed tar file in a file
manager and you drag the file to another
Moniker-aware application, say Gnumeric, Gnumeric
would be using the same file that was openened by
the file manager instead of having two
uncompressed sets of files in your system.</p>
<p>The above scenario is particularly useful if you
have little space, or if the process of untaring a
file would take a long time.</p>
</div>
<div class="refsect3">
<a name="id405252"></a><h4>The propertycache: moniker</h4>
<p>Accessing individual properties over and over
might take quite some time due to the CORBA round
trips. The propertycache: moniker would be also a
shared library handler that would basically
activate the property moniker, and would set up
property listeners (which would be notified of
changes in the property data base).</p>
<p>So if your application does a lot of queries to
a property, you might just want to append this to
improve performance and not care about doing
clustered reads, the cache would do this for
you.</p>
<p>This is not implemented, as it requires the
property moniker to be written.</p>
</div>
</div>
<hr>
<div class="refsect2">
<a name="id405275"></a><h3>The accidental invention</h3>
<p>Monikers were invented originally in OLE2 to
implement Object Linking. The OLE2 programmers
accidentally invented an object naming system.</p>
<p>This object naming system is not only very powerful,
but it is extensible and it helps make the system more
consistent.</p>
</div>
<hr>
<div class="refsect2">
<a name="id405289"></a><h3>Monikers and the GNOME VFS</h3>
<p>
Some people ask: monikers look as if they are just
re-implementing the GNOME-VFS, why is that?</p>
<p>For a storage backend you can always use something
like bonobo_storage_new ("gnome-vfs") and get away
with life.</p>
<p>The main difference between the gnome-vfs, and
monikers is that monikers are used to implement an
object-based name space, while the gnome-vfs is a fine
abstraction for naming files and directories. The
moniker space goes well beyond this.</p>
<p>When Ettore, Nat and I designed the GNOME VFS in
Paris Ettore had a grander vision than Nat and I had.
Nat and I wanted exactly what the GNOME VFS is: an
asyncronous, pluggable virtual file system
implementation. Ettore wanted something more general,
something that would implement an object name space.
And some of the design decisions in the core of the
gnome-vfs reflect some of this thinking, but the API
and the infrastructure was limited to handling
files.</p>
<p>Various months later, we finally understood
completely the moniker system, and we realized that
monikers were an object naming space, and that if done
correctly monikers would be able to implement Ettore's
initial vision for having an object-based naming
space.</p>
</div>
<hr>
<div class="refsect2">
<a name="id405322"></a><h3>Open Issues</h3>
<p>We will need to research the implementation
requirements for asyncronous parsing and resolution of
Monikers.</p>
<p>Currently, both the Object Activation Framework and
Bonobo support asyncronous activation. Implementing
this for Monikers should not be hard, but might
require a few changes in the Moniker interface.</p>
</div>
<hr>
<div class="refsect2">
<a name="id405337"></a><h3>Conclusion</h3>
<p>Monikers are very powerful mechanisms that can unify
the name space of objects in the system and can be
used to provide a uniform access method for a wide
variety of tasks:</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc">
<li class="listitem"><p>Component initialization</p></li>
<li class="listitem"><p>Addressing objects</p></li>
<li class="listitem"><p>Addressing sub-objects in a compound
document.</p></li>
<li class="listitem"><p>Implementing Object Linking.</p></li>
<li class="listitem"><p>Implementing nested objects, and nested handlers for
file systems.</p></li>
</ul></div>
</div>
<hr>
<div class="refsect2">
<a name="id405374"></a><h3>Acknowledgements</h3>
<p>The Bonobo moniker implementation was done by
Michael Meeks.</p>
<p>The design for the Bonobo moniker system was done by
Ettore Perazzoli, Michael Meeks and myself.</p>
</div>
</div>
</div>
<div class="footer">
<hr>
Generated by GTK-Doc V1.16</div>
</body>
</html>
|