[Contents] [Previous] [Next] [Last]


Chapter 2
Development Overview

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


Using the Composer Plug-in Class Library


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


Writing Composer Plug-ins


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 RedLetter step. To return to this chapter, click in the tutorial file.

[Top


Importing Packages and Classes

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. 

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. RedLetter step

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


Defining the Class

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. RedLetter step

[Top] [Writing Composer Plug-ins] [Next Step


Overriding Methods 

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]


Overriding Plug-in Information Methods

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.

Composer window showing name, category, and hint

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


Overriding the perform Method

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:

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.  RedLetter step

     /* 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


Adding Methods

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. RedLetter step

    public boolean perform(Document document)
        throws IOException{
        ...
        colorize(text.getText(), out);
        ...
        }

[Top] [Writing Composer Plug-ins] [Next Step


Preparing for Running in the Testbed

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." RedLetter step

[Top] [Writing Composer Plug-ins] [Next Step


Inserting an Image

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


Using Dialog Boxes

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


Adding an AWT Dialog Box

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


Adding an IFC Dialog Box

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


Placing the Plug-in in a Java Package

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]


Internationalizing and Localizing 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]


Composer Plug-ins and Security


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


Registering a Plug-in as a Menu Option or Event Handler


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


Creating the Configuration File

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.

To create the configuration file for a plug-in, follow these steps:

  1. In your work directory for the plug-in, use a text editor to create a file with this name:
  2. netscape_plugin_composer.ini
  3. Enter the plug-in class name and interface string. Use the same format for each type of interface string:
  4. netscape.plugin.composer.propertyName=pluginPathName
  5. As the propertyName for each class, enter one of these "well-known" properties, which are used by the Composer Plug-in framework. Each property name links to an example of the property definition.
  6. As the pluginPathName parameter, enter the full pathname of the plug-in. For example:
  7. netscape.test.plugin.composer.EditRaw
    
    
  8. Use a colon-separated list to define the same property for more than one plug-in, as follows:
  9. netscape.plugin.composer.classes=\
        netscape.test.plugin.composer.Colorize\
    :netscape.test.plugin.composer.EditRaw\
    :netscape.test.plugin.composer.TagStrip\
  10. Save the file with the .ini configuration settings extension.

  11. When you package the plug-in, place this file at the top level of the archive file.

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.

[Top] [Registering a Plug-in]


Registering a Plug-in with the Classes Property

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

[Top] [Registering a Plug-in]


Registering a Plug-in Factory with the Factory Property

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:

[Top] [Registering a Plug-in]


Registering a Plug-in as an Image Encoder

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."

[Top] [Registering a Plug-in]


Registering a Plug-in as an Image Encoder Factory

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."

[Top] [Registering a Plug-in]


Registering a Plug-in as an Event Handler

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."

[Top] [Registering a Plug-in]


Registering as Both Menu Option and Event Handler

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:

For more information, see "Event Handler Plug-ins."

[Top] [Registering a Plug-in]


Compiling 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]


Running Plug-ins in the Testbed


[Top


About the Composer Testbed

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]


Using 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]


Debugging


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:

Netscape

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]


Troubleshooting


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.
  1. Type:
    SHELL=C:\COMMAND.COM C:\ /E:space /P
  2. Replace space with the number of bytes you want for the environment setting. For example:
    SHELL=C:\COMMAND.COM C:\ /E:4096 /P
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