[Contents] [Previous] [Next] [Last]
Once you have an idea for a plug-in for the Netscape Communicator Composer window, actual construction is easy. This chapter presents the Composer Plug-in class library and describes all of the steps involved in developing Composer Plug-ins, from writing the Java class to packaging, installation, and testing. Go through the tutorial in this chapter to create a basic Composer Plug-in.
The examples in this chapter come from the samples included in the source directory of the Composer Plug-in Kit. If you like, you can follow the steps in the tutorial, or you can examine the code in the sample plug-ins or the tutorial to see how they work.
Chapter 2 focuses on issues and processes that you will need to know about as you use the Composer Plug-in API. Chapters 3 through 10 focus on many of the topics in this chapter in more detail.
[Top]
The Composer Plug-in API is a set of classes that make up a platform-independent, object-oriented Java programming environment. Composer classes are grouped into three packages, each of which performs a different function in the API.
[Top]
When you write a Composer Plug-in, you start by defining the plug-in as a Java class whose methods do the work of the plug-in. This section takes you through the steps of writing a Composer Plug-in.
Note on RedLetter
Tutorial:
You can follow along and write a very basic plug-in that
you can compile, build, and run in the Testbed. This plug-in performs one
simple operation; it does not illustrate every topic that this chapter
describes. To see this tutorial, click .
To return to this chapter, click
in the tutorial file.
[Top]
Your first step is to import the packages whose classes and methods you want to use in your plug-in. Use standard Java format to import the Plugin class and other Composer Plug-in API and Java classes. This example imports the standard Java language IO package.
import java.io.*;
The SmallCaps sample, in the source folder of the Composer Plug-in Kit, uses classes in the Java IO and Color packages, along with those in the Composer Plug-in Composer and IO packages. Use the * (wild card character) to import the entire package rather than individual classes.
import java.io.*; import netscape.plugin.composer.*; import netscape.plugin.composer.io.*; import java.awt.Color;
Note:
If you define a package for your plug-in, place its
package definition at the start of your code. You won't need to package
the plug-in for learning and testing, but you may want to package
it later for shipping.
[Top] [Writing Composer Plug-ins] [Next Step]
All Composer Plug-ins extend the Plugin
class. You subclass from Plugin and override its methods to implement
the behavior of your plug-in. Plugin is like the Java Applet
or Application classes; each is the main class of either the plug-in,
the applet, or the application.
To define a plug-in class, you use standard Java syntax. Your plug-in must
be a public class so that it can be instantiated by name and so that classes
in other packages have access to its methods. This line from the SmallCaps
sample, located in the source folder of the Composer Plug-in Kit,
defines the SmallCaps class.
public class SmallCaps extends Plugin { }
[Top] [Writing Composer Plug-ins] [Next Step]
The next step is to override the Plugin class methods that provide the functionality of the Composer Plug-in. You override two types of methods: methods that provide basic plug-in information, and the perform method, which does the work of the plug-in.
[Top] [Writing Composer Plug-ins] [Next Step]
There are three Plugin class methods that you must override to provide basic information about the menu option plug-in. You do not need to supply this information for a plug-in that runs only as an event handler.
The examples below are from the plug-in sample SmallCaps.
public String getName() { return "Small Caps"; }
public String getCategory() { return "Character Tools"; }
public String getHint() { return "Capitalizes selected text like the Netscape Home Page."; }
This figure shows the SmallCaps sample's Name, Category, and Hint (on the Status line at the bottom) in the Composer interface. To find out how event handler plug-ins that are not registered as menu options handle this information, see "Order for Calling Event Handlers."
Note:
All three of these methods have default implementations
that return the name of the plug-in class.
If you intend to localize your plug-in for use in a different country, you can make this easier by using a Java resource bundle to store this information. To see how this works, examine the DocInfo and DocInfoResources samples or the IFCTest and IFCTestBundle samples.
[Top] [Writing Composer Plug-ins] [Next Step]
The most important part of your plug-in is the perform
method. This is the method that does the work of the plug-in, where you
add any functionality that your plug-in requires and call other methods
the plug-in uses.
When the user of the Composer window invokes a plug-in, its perform
method is called with the current document, transferring the flow of control
from the Composer to the plug-in. The plug-in can now examine and modify
the document. Document contents can change arbitrarily between calls to
perform. The plug-in can even be given two different documents
on two successive calls to perform.
The perform method has this syntax:
public boolean perform(Document document) throws IOException { ... };
The plug-in operates on the HTML document represented by the document parameter. This method returns a Boolean value:
Note:
If the plug-in implementation uses a dialog box, true
would be returned if the user clicked OK, and false if the user
clicked Cancel.
Besides clicking the Cancel or OK button, the only other way to end the perform method is for the method to throw an exception; this is roughly equivalent to returning a value of false from the point of view of the plug-in. For information about Java exceptions and exception handling, see your Java documentation.
To the body of the method, add the code that does the work of the plug-in. For example, the plug-in can select text, call other methods, or call user interface elements provided by the Java AWT package or Netscape IFC. These procedures are summarized in this chapter and are described in more detail in Chapters 3 through 10.
The rest of the Composer user interface is held in a modal state while your plug-in is executing. The plug-in should either finish quickly, or display a progress dialog or otherwise let the user know what is going on.
The following example is the perform method of the EditHomePage sample plug-in. It calls a single method.
public boolean perform(Document document){ Document.editDocument("http://www.netscape.com/index.html"); return true; }
In contast, this perform method, from the EditRaw sample plug-in, included in the Composer Plug-in API creates and displays a dialog box, waits for the user to dismiss the dialog box, and copies the new text back into the document.
public boolean perform(Document document) throws IOException{
/* Create a dialog box */ MyDialog dialog = new MyDialog("Edit Raw HTML", document); dialog.reshape(50, 50, 300, 300); /* Make the dialog box visible. */ dialog.show();
/* Make sure the dialog is on top and gets focus. */ dialog.requestFocus();
/* Wait for the user to exit the dialog box. */ boolean result = dialog.waitForExit();
/* Dispose of the native OS window associated with dialog box. */ dialog.dispose();
/* Write the changed HTML back to the document. */ if ( result ) { document.setText(dialog.getText()); } return result; }
Note:
You can design your plug-in methods so that they are easily localizable.
[Top] [Writing Composer Plug-ins] [Next Step]
At this point, add any classes and methods that your plug-in needs. These are called or referenced in the perform method. For example, the perform method in the Colorize sample calls the method colorize, which was written for this sample.
public boolean perform(Document document) throws IOException{ ... colorize(text.getText(), out); ... }
[Top] [Writing Composer Plug-ins] [Next Step]
You can use the Composer Testbed Java environment to develop and test your plug-ins from the command line, then bring them over to the Composer. If you decide to take advantage of the Testbed, you simply add a main method to your class definition. The main function has this format:
static public void main(String[] args) { netscape.test.plugin.Composer.Test.perform(args, new pluginName());
Use the args parameter to define
optional parameters, such as an input and output file and a work directory.
For a full description of args, see
the description of the Test class.
Use the full path of the perform method; this way you import only
the method and do not have to import the entire Test package.
The main method does not affect the normal operation of the plug-in;
you can remove it before shipping or leave it in.
The plug-in can now run as an application in the Testbed when you enter the this run code at the command line:
java -classpath yourClassPath yourPluginName args
The args... parameter is passed
to the main method of the plug-in, which forwards it to the Test
class.
For more information, see "Running Plug-ins in
the Testbed."
[Top] [Writing Composer Plug-ins] [Next Step]
Your plug-in can insert images or local files into the Composer page. You might want to add a particular image related to your company or some other theme. For example, the AddButton sample inserts a Netscape Now button that links to the Netscape home page.
To add images or files, a plug-in must construct the HTML code and supply the URL of the file to insert. To remove a file, the plug-in must be able to select the HTML code that inserts the image and delete it from the document. For steps to follow and an example, see "Inserting Images and Local Data Files."
[Top] [Writing Composer Plug-ins] [Next Step]
Your plug-in design may include a dialog box that allows the user to enter text, make choices about what the plug-in does, or display plug-in results. You can use either:
For details about using AWT and IFC to implement dialog boxes and other
graphical user interface elements, see "Displaying
Dialog Boxes." This chapter includes a tutorial that focusses
on creating a dialog box. For examples of sample plug-ins that use dialog
boxes, take a look at the source code of the samples EditRaw (AWT)
and IFCTest (IFC).
You do not need to define a dialog box if your plug-in works directly on
the text in response to the menu command. For an example, see the SmallCaps
sample.
The Composer Plug-in dialog box operates modally, that is, it does not
allow access to the Navigator Composer window while it is displayed. Be
sure to code your plug-in to support this mode of operation.
The Composer Plug-in dialog box typically has three buttons: OK, Cancel, and Apply.
[Top] [Writing Composer Plug-ins] [Next Step]
Composer Plug-in dialog boxes that use the Abstract Windowing Toolkit
(AWT) are based on the Java Frame class, which represents a simple
Java window. Among the tasks involved in using AWT to create a dialog box
are instantiating the dialog box, invoking the dialog box, creating the
dialog box class, writing the method that provides the action of the dialog
box, handling events and threads, and copying the text back to the document
from the dialog box. For more information and steps to follow, see
"Displaying Dialog Boxes."
The EditRaw sample, included in your Composer Plug-in Kit, creates
a dialog box with button and panel AWT UI elements and calls other methods
to carry out dialog box actions.
[Top] [Writing Composer Plug-ins] [Next Step]
To create Composer Plug-in dialog boxes, you can use the Netscape Internet
Foundation Classes (IFC), which are part of Communicator 4.0. Among the
tasks involved in using IFC to create a dialog box are creating an IFC
application to implement the plug-in, writing the method that provides
the action of the dialog box, and copying the text back to the document
from the dialog box. For more information, steps to follow, and a tutorial,
see "Displaying Dialog Boxes."
The IFCTest sample, included in your Composer Plug-in Kit, creates
a dialog box and calls other methods to carry out dialog box actions.
[Top] [Writing Composer Plug-ins] [Next Step]
It is good practice to define a Java package for your plug-in, just in case your plug-in's name conflicts with the name of a plug-in written by another developer. If you do this, the Java package definition of your plug-in should appear at the start of your code. If you decide to define a package, refer to your Java documentation.
[Top] [Writing Composer Plug-ins]
When you write a plug-in, your plans may include internationalization, localization, or both. If so, you can smooth the localization process by putting your plug-in's text strings in a Java resource bundle. When you are ready to localize, see your Java documentation.
To see how you can use a resource bundle in a Composer Plug-in, examine the DocInfo and DocInfoResources samples or the IFCTest and IFCTestBundle samples, in the source directory of the Composer Plug-in Kit. If you limit your plug-in to the subset of ResourceBundle functionality used in these samples, your plug-in will work and will be easy to port to its final interfaces. This example from Docinfo shows the main steps in localization, using the ResourceBundle class:
/* Get the contents of the resource bundle. */ static String getResource(String key){ if ( resources == null ) { resources = ResourceBundle.getBundle( "netscape.test.plugin.composer.DocInfoResources"); } String result = resources.getString(key); if ( result == null ) { result = key; } return result; }
[Top]
Communicator 4.0 has a new security model for Java code. Composer Plug-ins have the same security privileges as Java applets. When your plug-in wants to perform some action that could be a security risk, such as inserting a file, it asks the Netscape Security Manager for permission. This, in turn, asks the user for permission. If permission is granted, the plug-in is free to perform the action. If your plug-in reads or writes files, or loads a dynamic library, or otherwise does something that might be dangerous, you must upgrade to this new security model.
For examples of the way this security model works in plug-ins, take a look at the AddApplet and AddButton sample plug-ins, in the source folder of the Composer Plug-in Kit. Both of these plug-ins insert elements into a document.
The Composer Plug-in Kit classes.zip archive contains a stub version of the class netscape.security.SecurityManager. This allows you to use your existing Java development environment to write code that calls the Security Manager.
In order to have security privileges, your plug-in, like a Java applet, must be signed. For more information, see Using the JAR Packager and Netscape Object Signing.
[Top]
The way that a plug-in executes in the Composer window is determined by the way you register the plug-in in the user interface. You can register a Composer plug-in class as a menu option plug-in, as an event handler, or as both. To register a plug-in, create or edit the netscape_plugin_composer.ini configuration file.
[Top]
To register your plug-in in the Composer interface, you create a configuration file called netscape_plugin_composer.ini, in standard Java Properties file format. This file defines the interface properties for plug-ins. It contains the names and the user interface strings for all of the plug-in classes you are going to place in your zip or JAR archive when you package the plug-in. When you actually package the plug-in, be sure to place this file at the top level of the archive file.
The same configuration file can contain menu option plug-ins, event handler plug-ins, and image encoders. You must register a plug-in as a menu option to make it available as an option on the Composer Tools menu.
netscape_plugin_composer.ini
netscape.plugin.composer.propertyName=pluginPathName
netscape.test.plugin.composer.EditRaw
netscape.plugin.composer.classes=\ netscape.test.plugin.composer.Colorize\ :netscape.test.plugin.composer.EditRaw\ :netscape.test.plugin.composer.TagStrip\
For examples of each type of interface string, take a look at the netscape_plugin_composer.ini file for the Composer Plug-in samples. You'll find this file in the source directory of the Composer Plug-in Kit.
If registered with the classes property, a Composer Plug-in is available as a menu option on the Composer Tools menu. For example, this is the configuration file for the plug-in sample EditRaw:
netscape.plugin.composer.classes= netscape.test.plugin.composer.EditRaw
You can use a Factory class to create your plug-ins at runtime. The Factory object is used to build a menu structure. When Composer starts, it looks for the Factory property first. The Factory instance's getPlugins method is called to return an enumeration of plug-ins. This allows the list of plug-ins to be created at runtime.
If Factory is not present, the Composer uses the classes property. If you want the Composer to use the classes property, do not include Factory at all. Here is an example of the configuration file for a plug-in that uses the Factory interface:
netscape.plugin.composer.factory= netscape.test.plugin.composer.MyFactoryClass
If registered with the ImageEncoder property, a plug-in is available as a menu option on the Composer Tools menu. This is the configuration file for the plug-in sample TextImageEncoder:
netscape.plugin.composer.ImageEncoder.classes= netscape.test.plugin.composer.TextImageEncoder
For more information, see "Writing and Using Image Encoders."
The image encoder factory class plays the same role for image encoder plug-ins that the factory class does for Composer Plug-ins. This is the configuration file for the plug-in sample ImageEncoderFactory:
netscape.plugin.composer.ImageEncoderFactory= netscape.test.plugin.composer.ImageEncoderFactory
For more information, see "Writing and Using Image Encoders."
Event handler plug-ins execute in response to a Composer window event. To register a Composer Plug-in as an event handler, add a line with this format to the netscape_plugin_composer.ini file:
netscape.plugin.composer.eventHandlers=pluginPathName
The pluginPathName is the name of the class you are registering. This is the configuration file for the sample DocInfo, which is registered with both the classes and eventHandler properties:
netscape.plugin.composer.eventHandlers= netscape.test.plugin.composer.DocInfo
Plug-ins registered as event handlers do not appear on the Tools menu unless they are also registered as classes.
For more information, see "Event Handler Plug-ins."
You can register a Composer plug-in class as a menu option, as an event handler, or as both.
To register a both event handler and menu option, use the same pluginPathName in both the netscape.plugin.composer.eventHandlers and the netscape.plugin.composer.classes properties in the configuration file. When you register a plug-in as both menu option and event handler, the Composer creates two instances of the plug-in in memory.
The two instances can communicate using static variables, or using ad hoc information encoded in the document.
For example, the DocInfo sample is defined with both the classes and eventHandlers properties, as follows:
netscape.plugin.composer.classes= netscape.test.plugin.composer.DocInfo
netscape.plugin.composer.eventHandlers=\ netscape.test.plugin.composer.DocInfo
For more information, see "Event Handler Plug-ins."
Use the Java compiler, javac, to compile your plug-in. You must do this whether or not you plan to use the Testbed to test your plug-in. Use this format:
javac -classpath paths myClassName[.* | *.java]
The paths parameter specifies the paths, separated by semicolons, of the following elements:
The myClassName[.* | *.java] parameter holds either your plug-in class name (with the .java extension) to compile just your plug-in class or *.java to compile all of the classes in the directory. You might want to use the *.java format to keep all of the plug-ins in the directory up to date.
If you are working in MS Windows, you can place the compile command and the class paths in a batch file. You can use this batch file to compile your plug-in from the command line. For example, this file, named compile.bat, compiles all of the plug-ins in the C:\SAMPLE1 directory.
SET CLASSPATH=C:\SAMPLE1;c:\Cpkit\classes\classes.zip;c:\java\lib\classes.zip SET JAVAC=C:\java\bin\javac.exe %JAVAC% -classpath %CLASSPATH% *.java
After you compile, you simply place the plug-in files in a zip archive to run your plug-in in the Composer. You can test the plug-in as a set of .class files.
[Top]
[Top]
When you are ready to test it, you can run the plug-in like an application in the Composer Testbed environment. The Testbed is provided by the netscape.test.plugin.communicator package. This package is a set of classes that emulates the Composer side of the plug-in interface. You can develop and test plug-ins separately in the Testbed Java environment, then bring them over to the Composer.
The Testbed is made up of the following netscape.test.plugin.communicator package classes, which are called from the Testbed run code in the main() method of the plug-in or image encoder. See "Preparing for Running in the Testbed."
[Top] [Running Plug-ins in the Testbed]
If you set up your plug-in class as described in "Preparing for Running in the Testbed," you can test-run your plug-in from the command line during development. Use this code:
java -classpath yourClassPath pluginPath args
The classPath parameter is the full pathname of your plug-in class. For testing, this can be your work directory. The pluginPath parameter is the full name of your plug-in.
For the args parameter, use one or more of the following values. The arguments are passed to the main method of the plug-in, which forwards it to the Test class.
-plugin plugin | Plug-in to use. Default: netscape.plugin.composer.Plugin |
-in file | File to use as the input test document. Testing does not modify the file. Results of the plug-in are written to System.out. |
-out file | File to use as the output test document. |
-string string | String to use as the test document. Default: a small built-in test document. |
-workDir dir | Directory to use as work directory. Default: Java user.dir property. |
-eventName event | Simulate an event of the given name. |
For example:
java -classpath classPath netscape.test.plugin.composer.EditRaw -out out.htm
You can run the Test class from the command line without deriving
from or instantiating it. For special testing purposes, you might want
to try deriving from Test and overriding methods such as createDocument
and createPlugin.
All of the samples included in the Composer Plug-in API contain code that
allows them to run in the Testbed. For details, see "Preparing
for Running in the Testbed." For more information about the command
line run code and its parameters, see the Test
class.
[Top] [Running
Plug-ins in the Testbed]
It easy to use the Testbed for debugging. The Testbed captures plug-in output in an output file, which you can use to compare your results with your intentions for the plug-in. The output file shows:
Because its Test.perform
method calls System.exit, the Testbed always terminates, even
if the plug-in or the AWT has left threads running.
Note:
You can set both an input file and an output file for the
Testbed. See "Using the Testbed."
If you do not get the behavior you expect when you run a plug-in, compare
the original and final versions of the HTML in your document. If you like,
you can send this file to standard output, or you can route it to another
file or location. This example shows a sample Testbed output file, returned
by the Composer Plug-in sample, Tableize.
Testbed Output File
Plugin class: class netscape.test.plugin.composer.Tableize category: Other name: netscape.test.plugin.composer.Tableize hint: Hint for netscape.test.plugin.composer.Tableize ------------------------------- Original Document: <html><head><title>A test document</title></head> <body> <p><a href="http://www.netscape.com">Netscape</a></p> <p>The <b>quick <i>brown</i></b> fox <!-- selection start -->jumped <!-- selection end -->over the lazy dog.</p> </body> </html> ------------------------------- Calling plugin... ------------------------------- Final Document: <HTML><HEAD><TITLE>A test document</TITLE></HEAD> <BODY> <P><A HREF="http://www.netscape.com">Netscape</A></P> <P>The <B>quick <I>brown</I></B> fox <!-- selection start --> <TABLE BGCOLOR=#30c030><TR><TD>jumped </TD></TR></TABLE> <!-- selection end -->over the lazy dog.</P> </BODY> </HTML> -------------------------------
The Final Document code shows that the the plug-in created the green one-cell table around the selected text, "jumped," as intended:
The quick brown fox
jumped |
over the lazy dog.
You can also run your plug-in from an integrated development environment, such as Symantec Cafe. Be sure to add the Composer Plug-in classes.zip archive to your IDE class path.
[Top] [Running Plug-ins in the Testbed]
If you are not getting the results you expect from running your plug-in, check these troubleshooting tips:
Make sure that the compiler can find the Composer Plug-in classes. Are the pathnames in the compiler's class path correct? This is the most common cause of trouble. | |
In the import line, add * to each package name to import the entire package. This way, you make sure that you include any class the plug-in may need. | |
Check the case of class and method names in your code: Are the class names capitalized? Are words capitalized that should not be? For example, the word "boolean" is always lower case. | |
MS Windows 95: If the plug-in fails
to compile, you may be low on environment space. Edit the config.sys
file to increase this setting.
|
|
You may need to put the zip program zip.exe in PATH in your autoexec.bat file. Or, type it in at the command line. | |
If you are copying chunks of code from a sample, make sure that you have copied all that you need, including the statement terminators and braces. |
[Top] [Running Plug-ins in the Testbed] [Contents] [Previous] [Next] [Last]
Copyright © 1997 Netscape Communications Corporation