#

## Chapter 14

## An Overview of the Marimba Classes

Many of the classes you've been using to create channels and plug-ins throughout this book have been part of the standard Marimba APIs. Both Castanet and Bongo come with a suite of new Java classes that not only help implement the Castanet and Bongo tools themselves, but can help you create channels, plug-ins, and other tools.

This chapter provides a general overview of many of the classes contained in the Marimba classes and tells you in which library they are located. I'm not going to cover every possible Marimba class here–many of the classes in the `marimba.gui` package, for example, are covered in detail in the Official Marimba Guide To Bongo. And I'm going to go into more detail about the classes specific to Castanet and channel development than I am for other classes. After reading this chapter, however, you should have a good idea of all the possible classes and how they can be used.

For more information on any of these classes, API documentation is available online from the Marimba site at `http://www.marimba.com`, as a set of channels from`trans.marimba.com`, and on the CD for this book. Official Marimba Guide To Bongo also contains documentation for many of these classes.

### The marimba.channel Package

The packages you've used most often throughout this book, and the classes you will use time and time again as you develop your own channels are the classes contained in the `marimba.channel` package. These classes include the interfaces for creating applications and for managing the application context; they also include classes for treating applets as channels and for incorporating Bongo presentations into channels.

The `marimba.channel` classes are split amongst multiple .zip files, which you'll need to add to your `CLASSPATH` or to the search path for your development environment before you can use them. The `Application` and `ApplicationContext` interfaces are contained in the `marimba.zip` file for either Bongo or the Castanet Transmitter. For the other four channel classes, you'll need Bongo's `bongo.zip` library, or the Transmitter's `transmitter.zip` class.

The `Application` Interface

The `Application` interface defines the standard channel methods and events; implement this interface in your own classes to convert them into channels. The `Application` interface defines four event types for handling updates:

- `DATA_UPDATE_EVENT` is called just before the channel is updated, allowing you to save channel feedback data that may be sent along with the request.
- `DATA_AVAILABLE_EVENT` is where new channel data is downloaded and ready to be installed. Call the `installData()` method on the application context to install it.
- `DATA_INSTALLED_EVENT` is called in response to `installData()` to allow you to process the newly installed data.
- `DATA_NOTIFY_EVENT` is sent to inactive channels whose Data Available property has been set of "notify." The channel is instantiated, `setContext()` is called, and this event is posted.

The `Application` interface also defines the following methods:

`public abstract void handleEvent(Event)` process events.

`public abstract void setContext(ApplicationContext)` is called at startup with an instance of the current application context, this method should save that context and perform any very basic initialization tasks.

`public abstract void start()` is called when the channel is first started.

`public abstract void stop()` is called when the channel is stopped.

The `ApplicationContext` Interface

The `ApplicationContext` interface defines the environment in which the channel runs and provides a mechanism for accessing Castanet Tuner and channel features. An object that responds to the `ApplicationContext` methods is passed to the channel through the `setContext()` method; usually you'll store that object in an instance variable and call its methods later on as the channel executes.

The `ApplicationContext` defines the following methods:

> `public abstract boolean appendLog(byte[])` stores an array of bytes as a channel log entry, to be sent to the transmitter as feedback data during the next update. Returns false only if there was an error writing the log entry.

> `public abstract boolean appendLog(String)` is the same as the previous method, except the argument is `String`.

> `public abstract boolean channelFileExists(String)` returns true if the given relative path exists in the channel.

> `public abstract URL getBase()` returns the base URL for this channel.

> `public abstract String getChannelDirectory()` is an older version of `getDataDirectory`; this method is obsolete and will be removed from a later release.

> `public abstract String getChannelName()` returns the full name of the channel.

> `public abstract String getChannelStatus(String)` returns the current channel status (one of `"unsubscribed"`, `"subscribed"`, `"running"`).

> `public abstract URL getCodeBase()` returns the URL of the directory for the channel's code (might be the same as `getBase(`), used most often with applets).

> `public abstract URL getDataBase()` returns the URL for the data directory for this channel, which be used to store persistent local files.

> `public abstract String getDataDirectory()` returns the path name to the data directory for this channel.

> `public abstract String getParameter(String)` returns the value of an application parameter, as stored in the `properties.txt` file for the channel (and set in the Castanet Publish).

> `public abstract Updates getPendingUpdates()` returns an `Updates` object representing the changes that will be made to the channel in the course of the update. Returns null if there are no updates to be made.

> `public abstract byte[] getProfile()` returns an array of bytes representing the profile data for this channel. Will return empty of there is no profile data for this channel.

> `public abstract String getServerName()` returns the name of the server (transmitter) for this channel. The transmitter name is of the form `hostname:port`.

> `public abstract void installData(String)` requests the tuner to install all or part of newly arrived data. The argument is the relative path name of the file or directory to install.

> `public abstract String[] listChannelDirectory(String)` returns an array of strings representing the names of files in the given directory. To list the entire channel, use `"."` as the argument. Returns null if the path does not exist.

> `public abstract String[] listChannels()` returns an array of strings representing all the subscribed channels.

> `public abstract long publishTime()` returns the time that has passed since this channel was last published.

> `public abstract void removeChannel(String)` removes this channel.

> `public abstract void restart()` restarts the channel.

> `public abstract boolean setProfile(byte[])` stores the array of bytes as profile data for this channel, to be sent to the transmitter as feedback data during the next update. Returns false only if there was an error writing the profile.

> `public abstract void startChannel(String, String)` starts some other channel. The first argument is the same of the transmitter; the second is the name of the channel.

> `public abstract void stop()` stops the channel.

> `public abstract void subscribeChannel(String, String)` subscribes to a channel (don't start it). The arguments are the name of a transmitter and the name of the channel.

> `public abstract void unsubscribeChannel(String)` unsubscribes from the named channel.

> `public abstract void update()` updates the channel.

> `public abstract long updateTime()` returns the time that has passed since this channel was last updated.

`Updates`

The `Updates` class represents the changes that will be made to the channel as part of an update. You can get an instance of this class using the `getPendingUpdates()` method from the application context. Using these methods in the `Updates` class, you can get a collection of strings representing path names to files that will be created, deleted, or changed as part of the update.

> `public Enumeration getDeletes()` returns an `Enumeration` object, consisting of `Strings` which represent paths to any files which will be deleted as part of this update.

> `public Enumeration getCreates()` returns an `Enumeration` object, consisting of `Strings` which represent paths to any files that will be created as part of this update (new channel files).

> `public Enumeration getUpdates()` returns an `Enumeration` object, consisting of `Strings` that represent paths to any files which will change as part of the update.

#### `ApplicationFrame`

`ApplicationFrame` is a subclass of the standard `java.awt.Frame` class that implements a basic form of the `Application` interface. You can use this class to implement your own channels.

In addition to the methods defined by both the `java.awt.Frame` class and the `Application` interface, `ApplicationFrame` provides the instance variable context, which holds the application context for this channel, and the following methods:

> `public void notifyAvailable(String)` is called in response to the `DATA_AVAILABLE_EVENT` event. The argument is the path name to the top-level directory that needs installing. By default, this method calls `context.restart()` if the `Data Available` property is set to restart, and `context.install` is the property is set to install.

> `public void notifyInstall(String)` is called in response to the `DATA_INSTALL_EVENT` event. No default implementation.

`ApplicationPlayerFrame`

`ApplicationPlayerFrame` is a subclass of the `marimba.gui.PlayerFrame` class that implements the `Application` interface. Use it to create channels that use Bongo presentations for their user interface.

> `ApplicationPlayerFrame` supports all the `PlayerFrame` methods, all the `Application` methods, and also has the same base implementation as `ApplicationFrame`.

`AppletContext and AppletViewer`

The `AppletContext` interface extends the `java.applet.AppletContext` interface and is used to gain access to the application interface when applets are run as channels. Use the `getApplicationContext()` method to get that context object from inside an applet.

> `AppletViewer` is a of `ApplicationFrame` that implements `AppletContext` and `java.applet.AppletStub`. It's used by the Castanet Tuner to play applets as channels and to support most of the common applet context methods (`showDocument()`, `showStatus()`, and so on).

### The `marimba.plugin` Package

The classes in the `marimba.plugin` package are used to create transmitter plug-ins, including the standard `Plugin` class and the `RequestContext` interface, which provides information about the update reqeust the plug-in is processing.

The `marimba.plugin` classes are available only in the `transmitter.zip` class that comes with the Castanet Transmitter. You'll need to add that file to your `CLASSPATH` or to the search path for your development environment before you can use them.

`Plugin`

The `Plugin` class provides the basic behavior for a transmitter plug-in; subclass this class to create your own transmitter plug-ins. Your class will be instantiated when an update request is made to your channel; with an object that supports the `RequestContext` interface that gets passed along in the `processRequest()` method you can get information and data from that update reqeust and process it.

When you subclass the `Plugin` class, you'll generally override three methods: `init()`, `destroy()`, and `processRequest()`.

The `Plugin` class provides four static variables for setting the disposition of files that you add to the channel's index using `addFile` (you learned about all these dispositions in Chapter 12, "Creating Transmitter Plug-Ins"):

- `ALWAYS` sends the byte array to the tuner on every request.
- `ASK_ME`: When this data is requested, the plug-in should handle the request
- `IF_NEEDED` sends the byte array to the tuner only if the tuner doesn't already have that data.
- `PERSISTENT` treats the data is if it were a file (so it can be cached by proxies).

The `Plugin` class also provides these methods:

> ####

> Note

> This is not a complete list of methods in the `Plugin` class. Many standard `Plugin` methods are intended to be called by the transmitter to start or to interact with the plug-in and are not useful to you for your subclasses. See the API documentation for the full set of methods.

> `public Checksum calculateChecksum(byte[])` returns a checksum for the array of bytes.

> `public Checksum calculateChecksum(String)` returns a checksum for the file referred to by the argument (a relative path to a channel file).

> `public void destroy()` is called when the plug-in object is unloaded. Override this method to clean up after your plug-in.

> `public File getChannelFile(String)` returns a File object representing the path to a channel file.

> `public String getChannelName()` returns the name of the channel this plug-in operates on.

> `public File getDataFile(String)` returns a file object pointing to the path name for the plug-in's local data directory. You can safely read and write files to this directory.

> `public Vector getLogEntries(RequestContext)` returns all the log entries sent to the transmitter as part of the request.

> `public void init()` is called by the transmitter when the plug-in is first started. Override to provide your own initialization behavior.

> `public void processRequest(RequestContext)` processes a subscribe or update reqeust for this channel. Override this method to process logging or profile data or to customize a channel.

> `public void processUnsubscribe(RequestContext)` processes an unsubscribe reqeust for this channel. There will be no profile data, nor will any data be sent back to the tuner.

RequestContext

The `RequestContext` interface defines methods that allow a plug-in to get information about the channel making and update or subscribe request. Usually those methods are used in the `Plugin` class, which is passed an instance of `RequestContext` object by the transmitter.

> The `RequestContext` interface provides the following methods:

> `public abstract void addFile(String, byte[], int) throws IOException` adds the file data in the byte array to the channel file list with the name given by the string argument, and with the given integer file disposition.

> `public abstract void addFile(String, byte[], Checksum, int) throws IOException` is the same as the previous method but also allows you to specify the checksum of the data.

> `public abstract void addFile(String, File) throws IOException` adds the file referred to by the File to the file list with the path name given in the string argument.

> `public abstract void addFile(String, File, Checksum) throws IOException` is the same as the previous method but also allows you to specify the checksum of the file.

> `public abstract void deleteFile(String)` deletes the specified file from the channel file list.

> `public abstract byte[] getLoggingData()` returns the data logged by the channel as an array of bytes. Returns null if there is no logging data.

> `public abstract String getLogPrefix()` returns a string representing the IP number and date and time of the reqeust.

> `public abstract int getMinutesGMT()` returns the number of minutes off the GMT for the system that made the reqeust.

> `public abstract getOSarch()` returns the OS architecture of the system that made the request.

> `public abstract getOSname()` returns the OS name of the system that made the request.

> `public abstract getOSversion()` returns the OS version of the system that made the request.

> `public abstract byte[] getProfileData()` returns the profile data for the channel as an array of bytes. Returns null if there is no profile data.

> `public abstract int getProtocolVersion()` returns the transmitter protocol version number.

> `public abstract String getRequestComment()` returns the reqeust comment (sent as part of the reqeust) and null if there is no comment.

> `public abstract long getTunerID()` returns a long integer representing the ID of the requesting tuner

> `public abstract String getTunerIDString()` returns a string object representing the ID of the requesting tuner.

> `public abstract void redirect(String, int)` redirects this reqeust to another transmitter. The string argument is the name of the transmitter, and the `int` is the port number.

> `public abstract void renameFile(String, String)` renames the file from the channel list specified in the first string argument to the name or path of the second string argument.

> `public abstract void setRequestDelay(int)` sets the delay in minutes before the tuner should make a second update reqeust.

`LogEntry`

The `LogEntry` class is a simple class for dealing with channel log entries. The `Vector` object created by the `getLogEntries` method (from the `Plugin` class) contains a `LogEntry` object for each of the log entries.

The `LogEntry` class has two instance variables:

- `timestamp`: The time and data the log entry was made
- `data`: The data that was logged for this entry.

The marimba.io Package

The `marimba.io` package provides classes for input and output to supplement the standard `java.io` classes. The most significant of those classes are the `FastInputStream` and `FastOutputStream` classes, which provide optimized unsynchronized buffered input and output streams.

The `marimba.io` package is part of the `marimba.zip` library (in either the Castanet Transmitter or Bongo releases).

`FastInputStream` and `FastOutputStream`

The `FastInputStream` and `FastOutputStream` classes, as I mentioned, provide input and output streams that are fast versions of a combination of the buffered, byte array, and data and print streams from the standard `java.io` package. Use `FastInputStream` and `FastOutputStream` for reading to and writing from files or arrays of bytes.

`FastInputStream`

`FastInputStream` extends the `java.io.FilterInputStream` class and implements the `DataInput` interface. You can create `FastInputStream` in a multitude of different ways:

> `FastInputStream(byte[])` creates a stream that reads from a byte array.

> `FastInputStream(byte[], int, int)` creates a stream that reads from a byte array (the two integers are the offset and length of the array).

> `FastInputStream(String)` opens a file.

> `FastInputStream(File)` opens the given file.

> `FastInputStream(InputStream)` combines two streams.

> `FastInputStream(InputStream, int)` combines two streams given a buffer size.

> `FastInputStream(RandomAccessFile)` accesses a `RandomAccessFile` stream

In addition to the standard methods available from its superclasses and the `DataInput` interface, `FastInputStream` includes the following additional methods:

> `public boolean backup(int)` backs up by a given amount (usually just one character or a small amount near the beginning of a stream).

> `public boolean getError()` sees if there has been an I/O error. (I/O errors are only reported when the stream is closed.)

> `public PropertyObject readObject()` reads a persistent object into a `PropertyObject` instance. (See the section on `marimba.persist` in this chapter for more information about persistent objects.)

`FastOutputStream`

`FastOutputStreams` are analogous to `FastInputStreams`; the `FastOutputStream` class inherits from `java.io.FilterOutputStream` and implements the `DataInput` interface. `FastOutputStreams` combine the best features of `DataOutputStream`, `PrintStream`, and `BufferedOutputStream`.

You can create a new `FastOutputStream` using one of these constructors:

> `FastOutputStream()` creates a memory-output stream.

> `FastOutputStream(int)` creates a memory output stream with a given size.

> `FastOutputStream(byte[])` creates a memory-output to the given byte array.

> `FastOutputStream(File)` opens the given file for writing.

> `FastOutputStream(String)` opens a file for writing.

> `FastOutputStream(OutputStream)` combines two output streams.

> `FastOutputStream(OutputStream, int)` combines two streams given a buffer size.

> `FastOutputStream(RandomAccessFile)` opens using a random access file.

In addition to the standard methods available from its superclasses and the `DataInput` interface, `FastOutputStream`s also implement all the printing methods from `PrintStream`, and the following methods:

> `public boolean getError()` returns true if there has been a write error. (Write errors are not reported until the stream is closed or flushed.)

> `public void justClose()` is a version of the `close()` method that doesn't throw an exception.

> `public void writeObject(PropertyObject)` writes a `PropertyObject` object to the stream. See the section on the `marimba.persist` package for more information.

Other Classes

The `marimba.io` package also contains the following classes, which you may find useful:

- `RAFInputStream` (inherits from `java.io.InputStream`) creates an input stream to interface to a `RandomAccessFile`.
- `RAFOutputStream` (inherits from `java.io.OuputStream`) creates an output stream to interface to a `RandomAccessFile`.
- `ScannerInputStream` (inherits from `FastInputStream`) is a fast efficient string parser.

The `marimba.gui` Package

The `marimba.gui` package contains the classes that constitute Java support for Bongo and its widgets. Although this is a very large package, I'm not going to cover all of it in this chapter; here I'll focus on the parts we've covered throughout this book and that are useful to channel developers. See the API documentation or Official Marimba Guide to Bongo for more information.

The `marimba.gui` package is part of the `bongo.zip` library. Because this library will not be part of the standard tuner distribution (it was in previous beta releases of the tuner), you should include it with every channel that uses any of its classes.

(d)PlayerUtil

The `PlayerUtil` class allows you to manipulate the widgets in a presentation from the class that uses that presentation. For channels built from the `ApplicationPlayerFrame` class, you can get to the `PlayerUtil` object for the current presentation via the `util` instance variable.

The `PlayerUtil` class provides the following methods:

> ####

> Note

> Many of these methods only apply to specific widget classes in the presentation, and others are only meaningful on specific widgets. You should be familiar with the widgets you use so that the values you get and set from those widgets to not surprise you.

> `public void addList(String, ListItemWidget)` adds the `ListItemWidget` in the second argument to the `ListWidget` named in the first argument.

> `public void addSortedList(String, ListItemWidget)` adds a `ListItemWidget` to a named `ListWidget`, sorted by the key.

> `public void appendText(String, String)` appends the string in the second argument to the `TextWidget` or `TextAreaWidget` named in the first string argument.

> `public void clearList(String)` clears the `ListWidget` named in the argument.

> `public void clearText(String, long)` clears the `TextWidget` or `TextAreaWidget` named in the first argument, after the number of milliseconds in the second argument.

> `public String currentPage(String)` returns the current page of the `FolderWidget` named in the argument.

> `public boolean getBoolean(String)` gets the value of the `CheckBoxWidget` or `OptionWidget` named in the argument.

> `public String getChoice(String)` gets the value of the `ChoiceWidget` named in the argument.

> `public PlayerPanel getPlayerPanel()` returns the `PlayerPanel` object for this presentation. (The `PlayerPanel` is a subclass of `java.awt.Panel` that displays a presentation.)

> `public Presentation getPresentation()` gets the current presentation.

> `public String getText(String)` gets the text of the widget named in the string argument.

> `public Object getValue(String)` gets the value of the widget named in the argument.

> `public synchronized Widget getWidget(String)` returns the widget object referenced by name in the argument.

> `public void gotoPage(String)` goes to the page named by the argument.

> `public void setBoolean(String, boolean)` sets the value of the `CheckBoxWidget` or `OptionWidget` named in the first argument to the value of the second argument.

> `public void setChoice(String, String)` sets the value of the `ChoiceWidget` named in the first argument to the value of the second argument.

> `public void setFPS(String, int)` sets the frames per second for the `AnimatedWidget` listed in the argument to the speed in the second argument.

> `public synchronized void setPresentation(String)` sets the current presentation, located at this path and filename.

> `public synchronized void setPresentation(URL)` sets the current presentation, located at the given URL.

> `public void setText(String, String)` sets the text of the widget named in the first string argument to have the value of the second string argument.

> `public void setValue(String, Object)` sets the value of the widget named in the string argument to the value of the object argument.

> `public void show(String)` shows the widget named by the first argument.

> `public void show(String, boolean)` shows or hides the widget named by the first argument. If the second argument is true, this shows the widget; if false, hides the widget.

`Widget` and its Subclasses

The `Widget` class is the generic class for all Bongo widgets, and includes a set of standard properties and behaviors for all widgets. All the widget classes in the `marimba.gui` class inherit from this class.

`Widget` is a large class and contains many of the same methods available from `PlayerUtil` to get an set various values of a widget. For more information on the variables and methods in `Widget` and its subclasses, see the API documentation or Official Marimba Guide to Bongo.

PlayerFrame

The `PlayerFrame` class is a subclass of `java.awt.Frame` that displays a Bongo presentation in a window. Usually with a channel, you'll subclass `ApplicationPlayerFrame` so that your Java program can respond to channel events; however, if your channel uses subwindows with separate bongo presentations you'll want to subclass `PlayerFrame` instead.

### The `marimba.persist` Package

The `marimba.persist` package contains classes that helps freeze the state of objects–which usually means saving them to files. These classes are used as part of Bongo to help widgets store themselves and their properties. If you're interested in learning more about widget persistence, Official Marimba Guide to Bongo has details.

The `marimba.persist` classes are stored in the marimba.zip class, available from either the Castanet Transmitter or Bongo releases.

The `marimba.desktop` Package

The `marimba.desktop` package contains classes that allow Bongo widgets and classes that use Bongo to interact with the native desktop. These classes are, for the most part, used internally by Bongo, with a few notable exceptions: four classes for adding a menubar and menus to presentations being displayed in `PlayerFrame` or `ApplicationPlayerFrame`. These classes behave nearly identically to the `java.awt` classes for menus (in fact, they inherit from those classes and are effectively Bongo-based wrappers for that AWT functionality), and include

- `AppMenuBar` (inherits from `java.awt.MenuBar`) is used to add a menubar to the frame playing this presentation.
- `AppMenu` (inherits from `java.awt.Menu`) is an individual menu, which can be added to a menubar.
- `AppMenuItem` (inherits from `java.awt.MenuItem`) is an individual menu item that can be added to a menu.
- `AppCheckboxMenuItem` (inherits from `java.awt.CheckBoxMenuItem`) is a specialized menu item that can be checked or unchecked.

The `marimba.text` Package

The `marimba.text` package contains classes for implementing a rich text editor–used by Bongo for its script editor. These are utility classes that you generally won't use in your own classes. `marimba.text` is part of the `bongo.zip` library and includes

- The `marimba.text.editor` package, with classes for the actual Bongo editor.
- The `marimba.text.keymap` package, with classes to handle special keyboard combinations and key mappings.
- `ByteString`, a structure representing a collection of bytes.
- `DeviceFont`, a subclass of the `java.lang.Font` class for device-specific fonts.
- `Mark`, to mark and go to a place in the text.
- `Style`, a representation of a text style.
- `StyleChange`, a position in the text where the style should change to something else.
- `StylePool`, a class that maintains an array of styles and their positions in a document.
- `Text`, an class for managing styled text.
- `TextView`, abstract view of a `Text` object (for example, a single or multiline text widget).

###
The marimba.util Package

The `marimba.util` package provides assorted utility classes for the other Marimba classes. Although these classes are generally only useful to the Marimba software, they are worth a mention here.

The `marimba.util` package is contained in the `marimba.zip` library, in either the Castanet Transmitter or Bongo distributions, and includes the following classes and interfaces:

- `Checksum` is a class that represents a 128-bit MD5 checksum. You can create a checksum from a variety of sources including files and strings.
- `Environment` is an interface to native desktop capabilities (for example, loading URLs and copy/paste).
- `Password` is a class that encrypts and decrypts passwords, using base64 encoding.
- `Props` is a subclass of `java.util.Properties` that provides features including for headers, filenames, and case insensitivity
- `PWEncoder` is a subclass of `sun.misc.BASE64Encoder` that doesn't add a newline.
- `QuickSort` is a class to sort things using a `QuickSort` algorithm (optimized for strings).
- `ThreadUtil` is a helper class for threads, mostly to find the current thread group.
- `Sortable` is an interface for sortable things.

### Summary

Do any work developing Castanet channels, and you'll end up touching the classes in the various Marimba packages. (Often you'll end up putting your hands all over them, actually.) In this chapter you got a general overview of the classes available to you in the marimba packages, in which zip libraries they can be found and, in the case of the more important classes, the sorts of things you can do with them.

Congratulations! You've reached the end of Official Marimba Guide to Castanet. After slogging through all 14 chapters in this book, you've now learned nearly everything you'll need to know about using the Castanet software and creating channels. Stay tuned to the Marimba home page and to the mailing lists for new information and details on further releases, and good luck!