Resource Bundling for Distributed Computing
Douglas Lyon, Fairfield University, Fairfield CT, U.S.A.
|
 |
COLUMN

PDF Version |
Wantonly hacked by an endless stream of nameless,
faceless undergraduates,
both men and women,
often by more than one at the same time,
Kahindu fell into a hell-hole of depravity.
–
DL, 1998
Abstract
This paper describes techniques for integrating programs and their
resources. The goal is to distribute the programs, to a variety of
platforms, without loosing the resources that they need in order to
run. Programs so integrated are less fragile than their non-integrated
counterparts. The techniques described include the use of a semi-automatic
source code synthesizer, XML-based serialization and a base-64 GZIP
encoded string format.
The approach is suitable for small data objects
(i.e., icons, short audio signals, etc.). It has been used, with
good success, on a variety
of projects. One drawback of the technique is that an added step
is required during program development in order to integrate resources
into the code. Another drawback is that integrating resources into
the source code can dramatically increase the size of the class files.
On the other hand, once the class files are loaded, the resources
are
available in memory (and hence, quickly accessible).
The techniques
described are a part of the Kahindu project, a joint project between
the skunk works of DocJava, Inc. and Fairfield University.
Kahindu is the name of a village in Kenya known for its fine coffee.
1 INTRODUCTION
One of the basic problems with Java programs is the fragility
that results when data is decoupled from source code. For example,
suppose
that you write a program that seeks to make use of an icon in an
interface. In order to load the icon, you write:
LookAndFeel.makeIcon(getClass(), "icons/ColorIcon.gif"));
Now
suppose the GIF “ColorIcon” icon file is relocated,
relative to the root of the source code. This can easily happen during
the process of distribution or development. Even worse, the missing
resource is not detected until run-time (perhaps days or even weeks
after deployment). For example, if you try to deploy an application
that attempts to obtain the above icon, without having it properly
integrated into the application, you would throw an exception, like:

Wouldn’t it be
nice if the compiler could make sure that our resources were present,
before run-time? In this way, we trade off a run-time error for
a compile-time error. We present some techniques that allow resources to be integrated
directly into source code. The result is a self-contained resource without the
normal source of fragility (i.e., source relocation). Hence, we no longer have
a program that requires files to be located in particular places on the disk.
The
presented technique can be used for any type of resource. Initially,
we focus on icons. We present the ability to create icons in one
of three ways: by grabbing
the icon using a screen grabbing program, by drawing the icon using either
the Kahindu drawing tools or another paint program and finally, by
entering the icon
using teletype graphics. Finally we present an encoding technique that automatically
generates Java source code from serializable instances. Icon Design by Grabbing
There are often icons that are available as
a system resource that can be freely copied. These icons start as bit-maps
and may be scaled
in size to suite the
application. The Kahindu program will accept icons of any size. Several applications
are able to take snapshots of the computer screen. These applications vary from
platform to platform. For example, Silicon Graphics workstations have an application
called Snap, which will save a snapshot of the screen. On the Mac there is a
keyboard shortcut, <shift-Moth-4> (or the grab application) which changes
the cursor into a cross hair and allows the user to click and drag across the
screen.
Depending on the platform, the screen shot will be saved to a file
or to a clipboard. The clipboard enables the screen shot to be pasted
into another
application.
Unfortunately, Kahindu is rather limited in the number of file types that it
currently supports. Thus, a third-party application is required to convert
the snapshot into an image that Kahindu supports. Currently, this means
GIF, PPM
or JPEG files. Suppose, for example, we wanted to grab the icon image from
the system to symbolize magnification. Fig. 1-1 shows an image of the
magnifier icon.
This was grabbed using the screen capture facilities on a Mac.
 Fig. 1-1. The Magnifier Icon
Using an application called Debabelizer [Debabelizer], we save the
icon image to a GIF file and open it with the Kahindu program.

Fig. 1-2. Save As Binary Icon
Fig. 1-2 shows that the Kahindu program has a menu for saving the
binary icon image.

Fig. 1-3. Binary Icon Output as Java
Fig. 1-3 shows the binary icon output at the console as a two-dimensional
static byte array. Such data takes very little space in the program
(15x15 = 225 bytes) and its’ space is allocated at compile time.
Icon
Design by Drawing
Another method for obtaining a binary icon is to
draw it. Several excellent paint programs are available that can
help with drawing
icons (including
Kahindu).

Fig. 1-4. The Kahindu Toolbar
Fig. 1-4 shows an image of the Kahindu toolbar. From left to right,
the icons are identified as the eraser, pencil, paintbrush, hand, magnifier,
marquee, paint can, eyedropper, and marker. To draw or modify an existing
icon, use the eraser, pencil, brush, magnifier and eyedropper. The
eraser will clear pixels in the icon. The pencil will set pixels to
the value selected with the eyedropper. The brush will set a larger
array of pixels than the pencil. Normally, the icons are small. The
Kahindu toolbar icons are all 15x15 pixels in size. As a result, the
magnifier is used to make the image easier to work on.

Fig. 1-5. Using the Magnifier to Expand the Paint Brush
Fig. 1-5 shows an example of the use of the magnifier icon to enlarge
the paintbrush image. This type of enlargement works by doubling the
number of pixels in the icon, and thus growing the icon. To keep the
icon the same size, but to enlarge it on the screen, simply resize
the frame. Once the frame is enlarged, use the drawing tools to modify
the icon.

Fig. 1-6. Elements of One Icon Can Be Used to Create Another
Fig. 1-6 shows how the bristles of the brush were reused to make a
face. The design of icons is an art and it takes great care to find
icons that have cross-cultural meaning. For example, icons should probably
not contain English language characters, as these are not well known
in all cultures.
Icon Design by Typing
The programmer can design icons by
hand-keying them into the byte array. The IconFrame class resides
in the Kahindu gui package. It
contains
several icons, some of which were typed by hand. Sometimes this
is the easiest way to enter an icon, as it gives fine-grained control
over the value and location of each pixel.

Fig. 1-7. Hand Typing an Icon
Fig. 1-7 shows the marker icon, as it was hand-encoded into the IconFrame.
The shift by exactly one pixel during each entry of the zeros in the
array, as well as the precise centering of the mark, is simplified
by hand entry. In fact, some programs (such as Maple) can output Teletype
graphics, like that shown in Fig. 1-7. The Internet is a good source
of Teletype graphics, as they are still e-mailed occasionally.
Saving the Icon as Java
Now that you have obtained the Java
source code needed for an image, you must assign it a name. This
is done in the IconFrame when the
static array is formulated in the Java code. For example:
Once the byte array is formulated, an IconComponent is created, using
the getIconComponent method:
The IconComponentinstances are added, using:

Once the icons are added to the iconPanel instance, they will be
available upon program start-up (i.e., without the need to access the
file system).
For use in Swing, programmers can get an instance of a javax.swing.
Icon by using:
Icon icon = Icons.getMagnifierIcon();
Event processing occurs
both in the IconFrame instance and in the frames that are associated
with the icon’s state. For example, in the PaintFrame,
there is a method called mouseDragged which checks the iconFrame instance
for the selected icon:
 The IconComponent instances act just like other components in the
AWT, except that they know how to invert their own appearance. They
can be added to panels
and layout managers can arrange them, just like other components. The IconComponent instance keeps a private copy of an image of its own appearance.
2 ON THE XML ENCODING OF SERIALIZABLE OBJECTS
This section
shows how an instance of a serializable class can be transformed
into a static variable. The static variable is used
to reconstruct the instance,
at run-time, thereby integrating the resource directly into the source
code. Consider the Address class, a fragment of which follows:

An instance of the Address converts itself to XML using the java.beans.XMLEncoder:
The XMLEncoder shows:

A static method in a utility class converts the above code into
a static string that can be embedded into a Java program: 
This can be decoded using:

Thus, we can test the XMLDecoder using:
 It is possible to serialize full-color images using XML, but this
is really inelegant. For example, an instance of the ShortImageBean:

becomes:

This uses 6 lines for every pixel! Such expansions
are too cumbersome even to contemplate. The following section addresses this
concern by using a base-64
GZIP encoding technique.
3 ON THE BASE-64 ENCODING OF SERIALIZABLE OBJECTS
This section
shows how to GZIP compress, and base-64 encode, an instance of an object,
so that it is suitable for storage into a Java string. This
is far
more efficient (in terms of memory and CPU time) than creating XML strings.
The technique suffers from the fact that the output is not readable by humans
and cannot be hand-edited.
The following example turns a full color image
into a base-64 GZIP encoded string, then decoded and displayed for
view.
 The following code shows how the GZIP base-64 encoder can be used
to synthesize a Java static variable declaration:
 The following
code example demonstrates how to decode the embedded object:

More generally, we write:

One drawback to this technique is that string constants can be too
long, causing the java compiler to choke. For example:

Even editing such files can
cause some IDEs (like IntelliJ) to bomb out. The question of how
to address this problem (perhaps by breaking
up the strings) remains open.
As a final example, we present a series
of icons used in our new GUI for image processing. These icons are
integrated into an Images class: 
The output of the new interface, with the integrated icons, is shown
in Fig. 2-1.

Fig. 2-1. The Application with Integrated Icons 4 CONCLUSION
In summary we look to avoid storing resources in external
files in order to speed resource loading and improve reliability
of our programs.
This is a natural outcome of resource integration with source code.
The
idea of storing icons in source code is not new [Lyon], but the idea
of storing serialized XML encoded objects in Java source
is
(as far as I know).
There are definite limitations to the technique
of storing objects
inside of a Java program. For one, there is a reliance on classes
implementing the serializable interface. For example, the Image class does not implement
the serializable interface. On the other hand, writing ad-hoc
techniques for storing images has the benefit of creating a
nice structure
for hand editing.
It is equally clear that large arrays of
data could create a cumbersome burden during compilation. In fact,
some compilers
will not allow
a static array that is larger than 64K bytes. It is generally
recognized that this is not a limitation of the Java language
specification,
but
rather of the implementation of the compiler.
Other failures
to serialize into Java source can result from using inner classes.
For example:

cannot work because Foo is an inner class.
REFERENCES
[Debabelizer] Debabelizer is a useful program for batch
image conversion and processing, available from: Equilibrium, 475 Gate
Five Road,
#225, Sausalito, CA 94965. Phone: (415)332-4343.
[Harder] Robert
W. Harder, “Base64”, A Public Domain Java
class providing very fast Base64 encoding and decoding in the form
of convenience methods and input/output streams. See http://iharder.sourceforge.net/base64/
[Lyon] Douglas A. Lyon, Image Processing in Java, Prentice Hall, Upper
Saddle River, NJ, 07458. 1999. Available from http://www.docjava.com
About the author

|
 |
After receiving his Ph.D. from Rensselaer
Polytechnic Institute, Dr. Lyon worked at AT&T Bell Laboratories.
He has also worked for the Jet Propulsion Laboratory at the California
Institute of Technology. He is currently the Chairman of the Computer
Engineering Department at Fairfield University, a senior member
of the IEEE and President of DocJava, Inc., a consulting firm in
Connecticut. E-mail Dr. Lyon at Lyon@DocJava.com. His website is
http://www.DocJava.com. |
Cite this column as follows: Douglas Lyon: “Resource Bundling
for Distributed Computing”, in Journal of Object Technology,
vol. 4, no. 1, January-February 2005, pp. 45-58. http://www.jot.fm/issues/issue_2005_01/column4
|