Chapter 21

Using ActiveX Controls with Java


CONTENTS

What is ActiveX? The best definition is pretty vague at best: an interface that is used to provide access to controls and code from various sources. It is mainly targeted at providing access to Internet applications. ActiveX was previously known as OLE. Then again, it is also based on the COM and DCOM models. These terms are often all used interchangeably.

There are several Visual J++ utilities that support creating the interface used to call ActiveX controls and creating an ActiveX control with Java. This chapter explores how ActiveX controls can be integrated with Java.

Creating the Java Interface Class

There are only a couple of steps required to create an interface to a COM object: registering the component and creating the Java interface class.

Registering an ActiveX Type Library

Registering a component involves putting some key information into the Windows Registry. This information must be present in the Registry to create a component.

Most installation programs automatically register a component during the install process. If, however, you have an unregistered component, you can use REGSVR32. This program must be run from a command prompt and has the following options:

regsvr32 [/u] [/s] dllname

The /u option provides the capability to unregister a DLL, and /s is used to run the program in silent mode.

To register components found in the file MYCONTROL.DLL, for example, the following line would be entered at a command prompt:

regsvr32 mycontrol.dll

Once a component is registered, a Java class can be generated to interface with the component.

Creating the Java Interface Classes

To use a COM component, a Java class and interface for use with the component must be generated. This can be accomplished by using either the Java Type Library Wizard or the command-line equivalent.

Java Type Library Wizard

The Java Type Library Wizard is used to determine the interface structure available to Java code that is used to interface to COM components. To access the Java Type Library Wizard, use the Tools | Java Type Library Wizard command. The dialog is displayed in Figure 21.1.

Figure 21.1 : Java Type Library Wizard.

This dialog displays all of the type libraries that have been registered. The dialog shows the name of the component. If a component is highlighted, the name of the source file is displayed at the bottom of the dialog. From the figure, you can see that the type library with the name Microsoft DAO 3.0 Object Library is located in the file C:\Program Files\Common Files\Microsoft Shared\DAO\Dao3032.DLL.

To create a class file and summary file for the COM object, click in the box next to the object. Figure 21.2 shows the selection of the Marquee object that is automatically installed with Internet Explorer 3.0.

Figure 21.2 : Marquee object selection.

After the OK button is pressed and the wizard has completed its tasks, you can see some very important information about the generated class in the Java Type Library Wizard tab of the Output window, as shown in Figure 21.3.

Figure 21.3 : Java Type Library Wizard tab of the Output window.

The first two lines contain the version of the wizard and let you know where the conversion utility came from. Unless you are a number cruncher, they will probably look fine. The next two lines are the most important for the developer. The import line is what needs to be added to the Java file where the COM object is to be used:

import marquee.*

The next line shows the filename of a file that was produced to show a summary of the objects created. Listing 21.1 shows the summary file that was generated for the Marquee object.

TIP
If you double-click the SUMMARY.TXT filename in the output window, Visual J++ will automatically display the contents of the summary file.


Listing 21.1. Listing of SUMMARY.TXT for the Marquee object.
public class marquee/Marquee extends java.lang.Object
{
}
public interface marquee/DMarqueeEvents extends com.ms.com.IUnknown
{
    public abstract void OnStartOfImage();
    public abstract void OnEndOfImage(int);
    public abstract void OnBounce(int);
    public abstract void OnLMouseClick();
    public abstract void OnScroll(int);
}
public interface marquee/IMarquee extends com.ms.com.IUnknown
{
    public abstract java.lang.String getScrollStyleY();
    public abstract void putScrollPixelsY(short);
    public abstract short getLoopsX();
    public abstract void putLoopsX(short);
    public abstract int getOffsetFromWndX();
    public abstract void putOffsetFromWndY(int);
    public abstract int getCurrentURL();
    public abstract void Resume();
    public abstract void putWidthOfPage(int);
    public abstract void Pause();
    public abstract java.lang.String getScrollStyleX();
    public abstract short getScrollPixelsY();
    public abstract void putScrollPixelsX(short);
    public abstract int getPageHeight();
    public abstract int getWidthOfPage();
    public abstract void putOffsetFromWndX(int);
    public abstract int getPageWidth();
    public abstract short getScrollPixelsX();
    public abstract int getWhiteSpace();
    public abstract void queryURLCount(int[]);
    public abstract void putScrollStyleY(java.lang.String);
    public abstract void putScrollDelay(short);
    public abstract void putDrawImmediately(short);
    public abstract short getPageFlippingOn();
    public abstract void insertURL(int, java.lang.String);
    public abstract void AboutBox();
    public abstract short getScrollDelay();
    public abstract void putCurrentURL(int);
    public abstract void deleteURL(int);
    public abstract void queryURL(int, java.lang.String[]);
    public abstract short getZoom();
    public abstract void putZoom(short);
    public abstract void putScrollStyleX(java.lang.String);
    public abstract void putBackgroundColor(int);
    public abstract short getDrawImmediately();
    public abstract void putPageFlippingOn(short);
    public abstract int getBackgroundColor();
    public abstract short getLoopsY();
    public abstract void putLoopsY(short);
    public abstract void putWhiteSpace(int);
    public abstract int getOffsetFromWndY();
}

This file contains what appears to be a Java class and two Java interfaces. The marquee/ prefixes to the class and interface names are not quite correct Java syntax, but are added for clarity. The class definition represents the COM object. Unfortunately, there are not too many methods that can be called in this class. However, the type wizard did provide two interface classes that can be called to access the COM object. A restriction of COM is that you cannot access the COM object directly for an instance of the COM class. Instead, you must always use the interface class.

The content of the interface classes represents the methods available in the COM object. Therefore, the documentation for the object would need to be consulted for the functionality of each method. For the Marquee example, visit the Microsoft Web page at www.microsoft.com/activex/ for more information. The complete page is included on the accompanying CD for your convenience, in example EX21A.

The Java Type Library Wizard generates the class information for each type library in the same location. This location is determined by the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\Java VM\TrustedLibsDirectory. Each library is stored in a subdirectory off of this directory with the name of the type library.

JAVATLB

Another way to generate the class information for a COM object is to use the command line equivalent of the Java Type Library Wizard, JAVATLB. The command-line syntax is

JAVATLB filename

where filename is the name of the type library. Again, the class information is stored off of the HKEY_LOCAL_MACHINE\Software\Microsoft\Java VM\TrustedLibsDirectory directory with the class files, and SUMMARY.TXT generated as if the Java Type Library Wizard were used.

Once the interface for the object has been created, it can be used by a Java applet.

Using a COM Object

Once an interface for a COM object has been generated, the object becomes as simple to use as any other Java class. The one exception is that when generating a COM interface, both a Java class and a Java interface are created. A COM class instance must always be allocated, but it must be accessed through the interface. This, however, will not be hard to remember, since the methods for a COM object are generated in the interface and the COM object class is rather dull.

Java applets and COM objects can communicate through two avenues: by passing a reference to a COM object directly to a Java applet so that the applet can call object methods and by passing events from a COM object to methods of a Java applet.

Passing COM Object References

The method that gives the Java applet the most control of the COM object is passing a reference to a COM object. This involves using a scripting language on an HTML page to reference both the COM object and the applet and then using the COM interface inside the applet to control the object.

Scripting Access to the COM Object

One limitation when working with COM objects is that if a COM object has a component that displays information, such as edit boxes for collecting user input information or radio buttons that allow the user to configure the use of an object, that COM object can not be instantiated in a program. However, if there are no interface components, an instance of a COM object can be instantiated directly in a program, as will be seen later.

To be able to access a visual COM object, a reference must be passed the program using a scripting language, such as VBScript or JScript. Consider the HTML of example EX21A, as shown in Listing 21.2.


Listing 21.2. HTML source for example EX21A.
<html>
<head>
<title>EX21A</title>
</head>
<script language=VBScript>
<!--
'Give the COM object to the applet
Sub window_onLoad
    document.EX21A.Load marquee
end sub
!-->
</script>
<body>
<OBJECT
    align=CENTER
    classid="clsid:1a4da620-6217-11cf-be62-0080c72edd2d"
    width=650 height=200 BORDER=1 HSPACE=5
    id=marquee
    >
    <PARAM NAME="ScrollStyleX" VALUE="Circular">
    <PARAM NAME="ScrollStyleY" VALUE="Circular">
    <PARAM NAME="szURL" VALUE="marquee.html">
    <PARAM NAME="ScrollDelay" VALUE=100>
    <PARAM NAME="LoopsX" VALUE=-1>
    <PARAM NAME="LoopsY" VALUE=-1>
    <PARAM NAME="ScrollPixelsX" VALUE=0>
    <PARAM NAME="ScrollPixelsY" VALUE=30>
    <PARAM NAME="DrawImmediately" VALUE=1>
    <PARAM NAME="Whitespace" VALUE=0>
    <PARAM NAME="PageFlippingOn" VALUE=1>
    <PARAM NAME="Zoom" VALUE=100>
    <PARAM NAME="WidthOfPage" VALUE=640>
</OBJECT>
<hr>
<applet
    code=EX21A.class
    id=EX21A
    width=650
    height=50 >
</applet>
<hr>
<a href="EX21A.java">The source.</a>
</body>
</html>

There are three important components of this source to examine. By examining the object from bottom to top, you see that the most obvious and familiar is the applet definition:

<applet
    code=EX21A.class
    id=EX21A
    width=650
    height=50 >
</applet>

These lines declare an applet on the page with the code contained in EX21A.class. An id of EX21A is associated with the applet so that the entity can be referred to elsewhere from the page. Sizing of the applet is the last element of the definition.

The next item is the OBJECT declaration. This object is an instance of the Marquee object discussed earlier in the chapter.

<OBJECT
align=CENTER
    classid="clsid:1a4da620-6217-11cf-be62-0080c72edd2d"
    width=650 height=200 BORDER=1 HSPACE=5
    id=marquee
    >

Notice that there is something distinctly missing from this OBJECT definition, namely, what it is. However, the classid does define the CLSID, which is a component-specific Universally Unique Global Identification (UUID) number. The Registry (using REGEDT32.EXE) can be consulted to determine what this component is. The following is some of a branch of the Registry key that gives information about this component:

HKEY_CLASSES_ROOT
    CLSID
        {1a4da620-6217-11cf-be62-0080c72edd2d}
            InprocSever32 = C:\WINDOWS\Sytem32\marquee.ocx
            Version = 1.0

This is the Marquee object. Additional information can be found in the HTML source that defines sizing of the object and an identification of marquee. Finally, before the OBJECT definition ends, there is a series of PARAM_NAME and VALUE pairs. These define values for the initial properties of the Marquee. Note that these parameters do not need to be specified as shown in this example. There are several options possible, including specifying the options in the HTML (as shown), using the default values of object (as documented in the Marquee documentation), or initializing the object via the Java interface once the object has been loaded.

The final component is the scripting portion of the HTML. This piece ties the applet and the COM object together.

<script language=VBScript>
<!--
'Give the COM object to the applet
Sub window_onLoad
    document.EX21A.Load marquee
end sub
!-->
</script>

The script language tag indicates that this code is VBScript. The only task completed in this script occurs in the window_onLoad event, which is generated when the page has been loaded. The function that is executed is the Load method of the EX21A object. The parameter passed to this method is marquee. Notice the reference to the two objects by their respective ids. As you will see in the next section, the Load method of the applet stores the reference to the object.

NOTE
To get more information on scripting VBScript or JScript, visit the Microsoft Web pages at http://www.microsoft.com/vbscript or http://www.microsoft.com/jscript, respectively.

Using the COM Object Interface

The previous section showed how the Marquee object was passed to the applet using VBScript in the HTML page. Once the object reference is loaded in the applet, example EX21A shows what can be done.

The Load method couldn't be simpler:

public void Load(Object marqueeObject)
{
    // save the reference to the object in the class
    MarqueeAccess = (IMarquee)marqueeObject;
}

The marqueeObject passed into the method is assumed to be the Marquee object. The reference to the object is saved in the member variable MarqueeAccess. Because the marquee is passed in as an object, a cast is done to the marquee interface class, Imarquee.

Once the object reference has been saved in the class, the rest of the program follows, as shown in Listing 21.3.


Listing 21.3. Control methods and class definition of EX21A.
public class EX21A extends Applet
{
    protected Button StateButton = new Button("Pause");
    protected IMarquee MarqueeAccess;
    public void init()
    {
        add(StateButton);               // provide control of marquee
        add(new Button("About"));
    }
    public boolean action(Event evt, Object obj)
    {
        boolean retval = false;
        if ("Pause".equals(obj)) {
            MarqueeAccess.Pause();      // stop the marquee
            StateButton.setLabel("Resume");
            retval = true;
        }
        else if ("Resume".equals(obj)) {
            MarqueeAccess.Resume();     // crank it back up
            StateButton.setLabel("Pause");
            retval = true;
        }
        else if ("About".equals(obj)) {
            MarqueeAccess.AboutBox();
            retval = true;
        }
        return retval;
    }
}

The class contains two variables, StateButton and MarqueeAccess, which are used to toggle the activity in the marquee and to hold a reference to the marquee, respectively.

The init method adds the State button to the Java portion of the page, which allows the user to control the starting and stopping of the movement in the marquee, and an About button, which is used to display a dialog containing version information about the Marquee control. The action method is similar to other examples throughout the book. If the Action button is pressed when the text on the button reads Pause, the Pause method of the marquee interface is called to stop the marquee from rotating. If the Action button is pressed when the text on the button reads Resume, the Resume method is called to continue the marquee. Lastly, if the About button is pressed, the AboutBox method is called to display some version information. Figure 21.4 shows the applet at work.

Figure 21.4 : Example EX21A.

As shown in the example, once the script has passed the COM object to the applet, the interface allows access to the COM object just as if it were a normal Java class.

Event Processing

The second method that can be used to communicate between the COM object and the Java applet implements event handlers in the applet. Again, scripting needs to be used as the interface between the two components.

COM objects can generate events when the control is in predefined states. The events can be caught by a HTML script and passed on. Revisiting the script code of the HTML file for example EX21A:

<script language=VBScript>
<!--
'Give the COM object to the applet
Sub window_onLoad
    document.EX21A.Load marquee
end sub
!-->
</script>

The subprogram is actually executed on an event when the window is loaded. This is how the script language can be used to respond to events. For this example, a predefined object was used to determine where the event originated from, window. To use this event processing for COM objects, simply reference the COM object by ID and add the event. To clarify, the OnLMouseClick event is generated by the marquee when the left mouse button is clicked on the object. The subprogram used to process the event would then be

Sub marquee_OnLMouseClick
    document.EX21B.Play
end sub

When the left mouse button is clicked on the marquee of EX21B, the Play method of the applet is called:

public void Play()
{
    // play the sound bite
    play(getCodeBase(), "bounce.au");
}

This method calls Applet.play to play a short sound bite.

Example EX21B illustrates how a two-way communication channel can be established between a COM object and a Java applet. First the object can be passed to the applet, which enables the applet to call the object methods directly. Secondly, the Java applet can respond to events generated by the COM object, with the help of a scripting language.

Nonvisual COM Objects

Visual objects require that a COM object be declared in HTML on the page. There are certain COM objects that do not require this. If a COM object does not have a corresponding visual component, an object does not have to be declared. Instead, an instance of the class can be instanciated in a Java applet directly.

Example EX21C illustrates this type of COM interface and shows how to implement a self-paging system. Figure 21.5 shows the paging system interface.

Figure 21.5 : Example EX21C.

To create the COM interface, use the Tools | Java Type Library Wizard in the MS Developer Studio. Select the Beeper 1.0 Type Library, as shown in Figure 21.6.

Figure 21.6 : Type Library used for example EX21C.

This dynamic link library contains a control that generates a beep, using the local machine's speaker. This is similar to generating an interrupt 0x07 in the olden days. The Java Type Library Wizard produces the summary file shown in Listing 21.4.


Listing 21.4. SUMMARY.TXT for the Beeper object.
public interface beeper/IBeeper extends com.ms.com.IUnknown
{
    public abstract int getCount();
    public abstract void Beep();
    public abstract com.ms.com.IUnknown get_NewEnum();
    public abstract java.lang.String getItem(int);
}
public class beeper/Beeper extends java.lang.Object
{
}

Of course, this control does not have a lot of options. Listing 21.5 shows the source for example EX21C.


Listing 21.5. Example EX21C.
import java.applet.*;
import java.awt.*;
import beeper.*;
public class EX21C extends Applet
{
    protected IBeeper Motorola;
    public void init()
    {
        // add a button so that an action can be performed
        add(new Button("Page"));
        // allocate a new COM object
        Motorola = (IBeeper)new Beeper();
    }
    public boolean action(Event evt, Object obj)
    {
        boolean retval = false;         // assume no action
        if ("Page".equals(obj)) {
            Motorola.Beep();
            retval = true;
        }
        return retval;
    }
}

The beeper interface is imported as usual. The init method adds the single button to the applet. Additionally, the init method allocates the COM object with the following line of code:

Motorola = (IBeeper)new Beeper();

Note that a class is allocated, since an interface instance cannot be allocated. Then, the returned object is cast to the interface object.

NOTE
A runtime error will occur if you attempt to use a COM object directly in a Java application, such as with the following code:
Beeper Motoroler = new Beeper();
Motoroler.Beep();

The action method in example EX21C responds the push of the button by calling the Beep method of the COM object to perform the page. I think I will recommend this pager to my boss.

Creating a COM Object with Java

So far, the discussion has been targeted to how most ActiveX objects will be used from Java applets and their interaction with Web pages. An additional feature of Visual J++ is that ActiveX objects can be generated. Follow these steps:

  1. Generate a UUID for the library and components of the library using GUIDGEN.EXE.
  2. Define the type library interface using the Object Definition Language (ODL).
  3. Create the type library from the ODL.
  4. Register the new COM component.
  5. Generate the Java Interface to the COM component.
  6. Implement the Java class for the COM component.

The following sections go over each step, developing a factorial example.

Generating a Universally Unique Global Identification (UUID)

The first step in creating a COM object is to establish a UUID number for the type of control. GUIDGEN.EXE can be used to create this number. Figure 21.7 shows this program in action.

Figure 21.7 : GUIDGEN.EXE.

This program guarantees that every number generated, no matter when or on what computer it is run, will be unique. In this way, every ActiveX object can be identified and verified with its UUID. Additional UUIDs will be needed for each element in the type library, as you will see in the next section.

Figure 21.7 shows that the number generated for the Factorial object is

{62133720-3022-11d0-BAF4-EC3AC9000000}

Defining an Object

The next step in defining the COM object is to determine the interface to the object. This is done using the Object Definition Language (ODL). ODL takes a general form of

[attributes] library libraryname {
    definitions
}

The brackets ([]) and braces ({}) are part of the syntax and are required. attributes is a comma-delimited list of ODL attributes. Typical contents of the list that applies to libraries include the UUID for the library, help information, and version number. libraryname is the name of the type library. definitions is the heart of the library and contains the datatype, interfaces, and class contained in the type library.

Using the UUID from the previous step, the Factorial object library for EX21D would then be

[
    uuid (62133720-3022-11d0-BAF4-EC3AC9000000),
    helpstring("Factorial 1.0 Type Library"),
    version(1.0)
]
library LFactorial
{
}

The contents of the library can include preprocessor directives, imported libraries, interfaces, and classes. The majority of these have the same general form.

[attributes] elementtype elementname {
    members
};

Again, attributes is a comma-delimited list of ODL attributes. This list contains UUIDs, help information, and a potentially large list of other information for complex elements. elementtype is one of the following keywords:

module
dispinterface
interface
coclass

elementname is the user-defined name given to the element. The members of the element are dependent on the type of the element.

ODL is an extensive language used to define types for OLE automation. What has been covered here is only enough to get your feet kind of damp, so that a basic understanding of the ODL file can be obtained.

NOTE
Microsoft's Interface Definition Language (MIDL) compiler can be used to compile ODL files, since the MIDL syntax contains complete support for ODL syntax. For a complete reference on MIDL, refer to the MIDL Programmer's Guide and Reference in the WIN32 SDK.

The Factorial object ODL is shown in Listing 21.6.


Listing 21.6. FACTORIAL.ODL.
[
    uuid (62133720-3022-11d0-BAF4-EC3AC9000000),
    helpstring("Factorial 1.0 Type Library"),
    version(1.0)
]
library LFactorial
{
    // get the standard stuff
    importlib("stdole32.tlb");
    [
        uuid (62133721-3022-11d0-BAF4-EC3AC9000000),
        helpstring("Factorial Interface")
    ]
    dispinterface IFactorial
    {
        properties:
        methods:
            [id(1)]long GetFactorial([in]long base);
    };
    [
        uuid (62133722-3022-11d0-BAF4-EC3AC9000000),
        helpstring("Factorial Class")
    ]
    coclass Factorial
    {
        dispinterface IFactorial;
    };
}

The Factorial object first imports the standard OLE objects using importlib. The dispinterface is used to define the properties and methods of the interface of the object. Notice that a UUID is given to the interface. The interface contains a single method, GetFactorial, that takes a number and returns the factorial of the number. Finally, the top-level Factorial class is defined with the coclass keyword. Again, a UUID is assigned to the top-level class. The class is made up of the single interface, IFactorial.

Creating a Type Library

Once an ODL file has been created, that file needs to be compiled into a type library. MKTYPLIB.EXE can be used. The syntax for this command line program is

MKTYPLIB [options] [inputfile]

The options for the program are shown in Table 21.1.

Table 21.1. MKTYPLIB options.

OptionDescription
/help or /?Display the options.
/tlb filenameNames the output filename to filename. The default is to use the input filename with the extension .tlb.
/h filenameSpecifies the filename of the optionally generated .H file.
/systemType of library that is to be made. system can be win16, win32, mac, mips, alpha, ppc, or ppc32.
/align #Sets alignment to #.
/o filenameCauses program output to go to filename instead of screen.
/nologoDisable display of copyright.
/w0Disable warnings.
/nocppDisable the C preprocessor. Java library creators should always use this option if the C compiler is not installed.
/cpp_cmd pathCauses the C preprocessor to use path.
/cpp_opt optSpecifies options to be sent to the C preprocessor.
/Ddefine[=value]Defines define for the preprocesser to an optional value of value.
/I includepathSpecifies an include file path.

The majority of the options are offered when libraries are being made for use when being called from C/C++ programs. This makes the version used for Java options quite simple:

mktyplib factorial.odl /nocpp

Registering the Component

Registering the component places important information about the object in the Registry. The JAVAREG.EXE command-line tool aides in registering Java COM objects. Figure 21.8 shows the command-line options available.

Figure 21.8 : JAVAREG.EXE options.

The command issued to register the Factorial class specifies the class name and the UUID, which will be used for the CLSID:

javareg /register /class:Factorial /clsid:{62133722-3022-11d0-BAF4-EC3AC9000000}

Creating the Java Interface

Once the COM object is registered, the COM interface class is generated. Once again, go to the Tools | Java Type Library Wizard, as shown in Figure 21.9, to generate the class.

Figure 21.9 : Factorial Type Library selection.

The SUMMARY.TXT file is shown in Listing 21.7, with the expected single GetFactorial method in the interface.


Listing 21.7. SUMMARY.TXT for the Factorial COM object.
public class factorial/Factorial extends java.lang.Object
{
}
public interface factorial/IFactorial extends com.ms.com.IUnknown
{
    public abstract int GetFactorial(int);
}

Implementing the Java Class

The final step in creating the Java Component is to implement the Java class defined in the ODL file. To do this, simply implement the interface class. Listing 21.8 contains the Factorial class.


Listing 21.8. Factorial class implementation.
import com.ms.com.*;
import factorial.*;
class Factorial implements IFactorial
{
    public int GetFactorial(int base)
    {
        int retval = 0;
        if (base >= 1 && base <= 20)
        {
            retval = 1;
            while (base > 1)
            {
                retval = retval * base;
                base-;
            }
        }
        return retval;
    }
}

The class that implements the IFactorial interface could have been named anything. There is not a direct correlation between the Factorial coclass in the ODL file with this Factorial class. It simply makes it easier for the programmer. Notice that the Factorial interface of the COM component is imported. The GetFactorial method calculates the factorial for a number between 1 and 20, returning the factorial of the number.

From this point, the Java class can be used from any application that can activate an ActiveX component. As an example, the next section will cover example EX21D, which is an applet that will use this object.

Using the Java Component

Using a COM object implemented with Java is just like using any other COM object. Figure 21.10 shows example EX21D and the COM object in use.

Figure 21.10 : Example EX21D using the Factorial COM object.

Listing 21.9 shows the action method from example EX21D, which illustrates the use of the COM object, iFac.


Listing 21.9. action method of example EX21D.
public boolean action(Event evt, Object obj)
{
    boolean retval = false;
    if ("Calculate".equals(obj))
    {
        try {
            int base = Integer.parseInt(BaseField.getText());
            int result = iFac.GetFactorial(base);
            if (result > 0)
                ResultLabel.setText(Integer.toString(result));
            else
                ResultLabel.setText("Error!");
        }
        catch (NumberFormatException e)
        {
            ResultLabel.setText("Bad #!");
        }
        // make sure the label is dipslaying all of its text
        ResultLabel.resize(ResultLabel.preferredSize());
        // tell the layout manager to do it's job again
        validate();
        retval = true;
    }

    return retval;
}

As you can see, there are just a few steps to creating an ActiveX object that can now be used in a number of situations. In addition, there are several command-line utilities in the Visual J++ suite that aide in completing these steps effortlessly. Once you have a component that is to be distributed, you must enclose the component in a signed CAB file so that a user can safely use the component without the fear of a security risk.

Creating a Signed CAB File

When distributing applets over the Internet, make sure that the users that visit your site feel safe about using any COM objects that have to be downloaded to their machine. After all, if the user does not feel safe, he or she won't use the component or visit the site. To accomplish a certain level confidence, and, in the process, gain speed of download via compressing the classes being used on your site, utilize signed cabinet files. Creating a signed CAB file is a two-step process: creating a CAB file with the classes needed for your applet and signing the file using Microsoft's Authenticode technology.

CAB Files

Cabinet file support is included on the Visual J++ disks in the \Cab&Sign directory. They are not automatically installed when installing Visual J++. To install the CAB file creation utility, copy CABDEVKIT.EXE to a directory on your local drive. Then execute the self-extracting file and follow the installation steps.

There are two steps in using a CAB file: creating the file and making use of the CAB file for your applet.

Creating a CAB File

Once the CAB Development kit has been installed, it is quite easy to create a CAB file. In fact, there are two ways to create a file: using the CABARC command or editing the sample .DDF files and running DIAMOND directly.

The CABARC utility has the following syntax:

CABARC [options] command cabfilename [filelist] [destdirectory]

command is a single letter indicating the type of function to perform: L (list), N (new CAB file), or X (extract). cabfilename is the name of the CAB file; remember to add the .CAB extension because it isn't automatically added. filelist is the list of files to add to the archive.

There are several options that can confirm files, set the compression type, and cause recursive inclusion of files in subdirectories (as well as other options) that can be seen by typing only the name of the command. One of the most important options is the -s option, which allows the user to reserve space in the archive for signing the CAB file.

As an example on the accompanying CD, the EX21E subdirectory contains the CAB files for distributing the EX15A example. The following command was used to create the CAB file:

CABARC -s 6144 -r -p N ..\..\Chap21\EX21E\EX15AArc *.class *.jpg

Unfortunately, this does expose an error that currently exists with this version of the CAB file concept. This technology is designed to have images and audio files included in the CAB files. The CAB should be checked when loading an image using a URL that is relative to the code base, as in the following snippet of code:

getImage(getCodeBase(), "images\\Christopher1.jpg");

If the image file is not found in the CAB file, normal processing should then dictate that the codebase is referenced for the file, as usual. Currently, the images and audio clips are not loaded from the CAB file at all. Therefore, for example EX21E, there is an image subdirectory that contains the images for EX15A.

The alternative method to using CABARC is to run the cabinet generating program, DIAMOND.EXE, explicitly. To do this, however, the default DDF files need to be modified to handle the applet classes explicitly. The default DDF files are heavily commented, so the modifications are straightforward.

First, copy the files CLASSPCK.DDF, MASTER.DDF, and MASTER.INF to the release directory so that these files can be modified. Then, edit CLASSPCK.DDF to create a CAB file that will contain the class files. Following the comment in this file, modify the CAB filename that will be generated and the class files that go into this CAB file. This is not the final CAB file but only a CAB file that will contain the class files. Create the CAB file with the command

DIAMOND /f ClassPck.ddf

Next, change the MASTER.INF file. Again following the comments in the file, add the control's CLSID and some identification information for the installed library. It might be a good idea to change the name of this file to reflect the product being distributed. Example EX21F, which contains all of these files and represents a distribution of example EX21D, changed the name of the master files to EX21DDiamond.

Finally, set the name of the final CAB file, name of the class CAB file and the name of the .INF file in MASTER.DDF, and create the CAB file with the final DDF file. For our example:

DIAMOND /f EX21DDiamond.ddf

As you can see, the first method is simpler while the second method allows much more flexibility. Once the CAB files have been created, they need to be used in the APPLET tags of the HTML.

Modifying the Applet Tag for CAB File Use

Using CAB files requires a simple modification to the HTML. A single additional parameter can be specified in the APPLET tag:

<APPLET
    code=EX15A.class
    id=EX15A
    width=500
    height=300 >
<PARAM NAME="cabbase" VALUE="EX15AArc.CAB">
</APPLET>

The cabbase parameter instructs CAB-enabled browsers, such as Internet Explorer 3.0, to use the specified CAB file for class information.

Signing a CAB File

Signing a CAB file is a process that attempts to secure some reliability of code integrity through the use of public and private keys and certification authorities for code that is distributed over a virtually uncontrolled Internet. The process involves applying for a public key through a certification process by which a business shows the validity and stability of their company. Once that has been established, a key is assigned to that company that allows anyone to trace a file digitally signed with that key back to the company.

Digital signing of files support is included on the Visual J++ disks in the \Cab&Sign directory. It is not automatically installed when installing Visual J++. To install the code signing utility, copy CODESIGN.EXE to a directory on your local drive. Then execute the self-extracting file and follow the installation steps.

This section covers how to digitally sign a CAB file with the test certificate supplied with the kit. You must contact a Certification Authority to obtain an authentic certification before distributing your CAB files. Visit http://www.microsoft.com/intdev/signcode for more information on Authenticode.

To generate a test certificate, use the MAKECERT.EXE utility. A possible invocation of this program to generate MATHWORKS.CER is

MAKECERT -k:MathWorks.pvk -n:CN=MathWorksInc -d:MathWorksInc MathWorks.cer

Once a test certification file has been created, CERT2SPC.EXE can be used to generate a SPC file:

CERT2SPC root.cer MathWorks.cer MathWorks.spc

The SPC file is the file that would normally be provided by the Certification Authority. These utilities are simply provided to test the process.

The SPC file is used to actually sign the CAB files. SIGNCODE.EXE is used to add a digital signature to a file. The easiest way to use this program is to simply enter name of the program without parameters:

SIGNCODE

The Code Signing Wizard of Figure 21.11 will simplify the process.

Figure 21.11 : Code Signing Wizard.

Once a CAB file has been digitally signed with a valid SPC file, it is ready to be distributed. There are two additional utilities that can be used to test the signing of files: PESIGMGR.EXE and CHKTRUST.EXE. These utilities can manipulate the certificates used in signing a file and checking the validity of a signed file, respectively. Remember that these will not work with the test certification generated with MAKECERT and CERT2SPC.

Summary

This chapter touched on several points involving the quickly changing ActiveX world. It covered how to create a Java interface of an ActiveX object using the Java Type Library Wizard for registered components. After establishing the interface, the Java applet can then be used to control the objects by calling the interface methods made available for the component. In addition, the Java applet could be used as an event handler. Combining these methods, two-way communications can be established between the object and the applet. Java can also be used to create an ActiveX object that can be packaged in a signed CAB file for trusted use on your favorite Web site.