|
|
|||
|
|
![]()
|
|
|
|
Chapter 35Adding Additional Protocols to HotJavaby David Baker
Anessential feature that Java attempts to
impart to computing is extensibility. Over time, newer and better
means of communicating will be created. Application protocols
will evolve and programs must be able to adapt. Support for new
protocols can be added to Java and the HotJava browser through
protocol handlers.
Protocol handlers are a key tool for maintaining an adaptable
environment with Java. They extend support to new URL schemes,
which can access new application protocols, or present existing
ones in new ways.
Protocol handlers enable you to accomplish two tasks: first, you
can implement a client for a defined network application protocol,
as demonstrated in the previous chapters; second, you can associate
this implementation with a new URL scheme. Thus, you can create
the code necessary to assign meaning to a new URL scheme.
HotJava can make use of new protocol handlers; this is part of the vision guiding HotJava's ongoing development. The intention is that programs like HotJava should have very little core intelligence, providing only a framework for extensibility. When new protocols are invented, HotJava will transparently download a new handler and the user can then access the resource. You can also utilize protocol handlers in your own applications. By installing a new protocol handler and using a registration facility termed a factory, URL objects can use these handlers just as the standard protocols are used. Protocol handlers are not a factor new to your Java programming. In fact, any time an URL object was used to obtain a resource in the previous chapters, a handler inherent in the JDK was used. With the steps that follow, you can create your own handlers to build on this existing set.
The examples within this chapter implement the NICNAME/WHOIS protocol,
defined in RFC 954. WHOIS is used by Internic, the domain name
registration and directory project, to enable individuals to query
their database. WHOIS can be used at rs.internic.net, but
other sites utilize this service. By opening a TCP socket to the
standard port 43, a query can be entered and the response read.
Step One: Decide Upon a Package NameA protocol handler must be placed into a clearly-defined package. This package must end in protocol.scheme where scheme is the new URL scheme. Generally, new packages also include the domain name and author identifier of the distributor. Thus, in this example the following package will be used: ORG.netspace.dwb.protocol.whois Step Two: Create the DirectoriesThe necessary code for the protocol handler must be placed into a directory named in correlation to the package name identified. This directory should reside within a directory into which your own Java code is placed, usually called classes within your home directory. Listing 35.1 shows an example for creating these directories under Windows NT and Windows 95. Lising 35.1 Creating the Directories Under Windows NT and Windows 95 %HOMEDRIVE% cd %HOMEPATH% mkdir classes mkdir classes\ORG mkdir classes\ORG\netspace mkdir classes\ORG\netspace\dwb mkdir classes\ORG\netspace\dwb\protocol mkdir classes\ORG\netspace\dwb\protocol\whois The process is similar under the UNIX operating system, as shown in Listing 35.2. Listing 35.2 Creating the Directories Under UNIX cd ~ mkdir classes mkdir classes/ORG mkdir classes/ORG/netspace mkdir classes/ORG/netspace/dwb mkdir classes/ORG/netspace/dwb/protocol mkdir classes/ORG/netspace/dwb/protocol/whois Step Three: Set Your CLASSPATHThe CLASSPATH environment variable tells the Java compiler and interpreter where to find Java classes, enabling the dynamic linking feature of the Java execution environment. When installing the JDK, HotJava, or a Java-aware browser, you may have set the CLASSPATH environment variable. If this is so, it is critical that you avoid overwriting that data. First, you must find out what your CLASSPATH current setting is. Under Windows NT/95, just type the following command: SET Look for the CLASSPATH value. Under UNIX systems, you can display the CLASSPATH value with this command: ECHO $CLASSPATH Now you need to reset your CLASSPATH, including the previous data, if any. Under Windows 95, if your CLASSPATH was .;C:\JAVA\LIB\CLASSES.ZIP, you can add the following line to your AUTOEXEC.BAT and reboot: SET CLASSPATH=.;%HOMEDRIVE%%HOMEPATH%\CLASSES;C:\JAVA\LIB\CLASSES.ZIP Under Windows NT, presuming that the CLASSPATH value was the same as under the Windows 95 example, use the System Control Panel to add a CLASSPATH environment variable with the value .; %HOMEDRIVE%%HOMEPATH%\CLASSES;C:\JAVA\LIB\CLASSES.ZIP. Under UNIX, assume that your old CLASSPATH was .:/usr/java/lib. If you are using the C shell, place the following into your .cshrc file:
If you are on a UNIX system using the Korn or a POSIX-compliant shell, add the following line to whatever file your ENV environment variable points. If ENV is unset, then you could add the line to your ~/.profile file:
Step Four: Implement the ProtocolWithin the directory created in Step Two, create a class that extends URLConnection. This class should have a constructor that takes an URL object as an argument and calls its superclass with that object. In addition, most protocol handlers should extend the following methods: public void connect() throws IOException; This method should connect to the remote resource and perform the network transaction, as appropriate. public String getContentType(); This method should indicate the MIME content type of the data returned by the object. public synchronized InputStream getInputStream() throws IOException; This returns an InputStream containing the data from the remote system.
Listing 35.3 shows the class used to implement the WHOIS protocol.
This class supports the URL formats shown in Table 35.1.
Listing 35.3 whoisURLConnection.java
The whoisURLConnection constructor merely makes the appropriate call to the URLConnection superclass, passing it the URL object. The connect() method is where all of the work is done. First, it creates a number of streams for reading in data and passing it back to your Java application. Next, it uses various URL class methods to parse the URL, supporting the formats identified in Table 35.1. The default values of the host (for example, "rs.internic.net") and port (i.e., "35") are stored within static final variables. Then, the connect() method opens a TCP socket connection to the remote system, sends the query, and prepares to read the response. It reads in the query response, embedding it within HTML. Finally, connect() closes the streams and TCP socket. The getContentType() method is used to indicate that the returned data is an HTML document. getInputStream() returns the PipedOutputStream, into which this protocol handler has pushed the formatted data. The Java application uses this stream to access the data obtained by the new protocol handler. The whoisURLConnection has an additional protected method called decodeURL(). Certain characters, such as spaces and other special characters, cannot be represented literally within URLs, and these characters are encoded with a special format. For example, a space is encoded as %20. Since your WHOIS query may need to use such characters, the WHOIS protocol handler must have a method to decode this data. decodeURL() is called from the connect() method, and examines a string byte-by-byte. When it encounters a percent-sign, it uses the next two characters as the Unicode value to the encoded char-acter. Step Five: Create the Handler ClassWithin the same directory, you must create a file called Handler.java. The Handler class must extend the URLStreamHandler class and return an instance of the class created in Step Four. Listing 35.4 shows the Handler class for the WHOIS protocol. Listing 35.4 Handler.java
Step Six: Compile the SourcesUse javac to compile the sources created in Steps Four and Five, leaving the compiled class files in the originating directory. Using Protocol Handlers with HotJava
Eventually, as part of HotJava's vision, protocol handlers will
be dynamically downloaded and utilized. At the time of this writing,
this feature is not yet supported by HotJava. Protocol handlers
must be manually installed, as previously described, in order
for HotJava to utilize them.
Once a protocol handler has been installed, the following additional
steps are necessary to use it within your HotJava browser.
Step One: Update the properties FileYou must instruct HotJava to load additional protocol handlers. This is done by updating the properties file, which is located within the .hotjava directory in your home directory. Within this file, you must set the java.protocol.handler.pkgs property to include the new protocol package. The value to add should be everything from the protocol token leftward. Thus, you want to add the following line for your WHOIS protocol handler: java.protocol.handler.pkgs=ORG.netspace.dwb.protocol If you already have this property set within your HotJava properties file, append a pipe character (i.e., |) to the end of the line and then add ORG.netspace.dwb.protocol. This syntax enables you to install several new protocol handlers, like the following: java.protocol.handler.pkgs=COM.company.protocol|ORG.netspace.dwb.protocol Step Two: Run HotJavaStart up HotJava and test out the new protocol handler. Go under the File menu, select Open Page, and type the following text into the URL field: whois:internic.net Figure 35.1 shows what should be displayed within the HotJava window. Figure 35.1 : HotJava using the WHOIS protocol handler. Using Protocol Handlers with Your Own ApplicationsThe usefulness of new protocol handlers extends beyond the HotJava browser. They can also be utilized within your own applications; the key step being a method to register the new protocol handler using a concept known as a factory. As an example, a simple application will be developed to make use of the WHOIS protocol handler. FetchWhois will take its arguments and send them as a query to the WHOIS service at rs.internic.net. The source of this example is shown in Listing 35.5. Listing 35.5 FetchWhois.java
The main() Method: Starting FetchWhoisThe simple main() method checks to see that the program was invoked properly. It then creates a FetchWhois object, passing it the array of command line arguments. The FetchWhois Constructor: Where the Work Gets DoneThe constructor is where the connection to rs.internic.net is opened through the use of your new protocol handler. The key line is where it uses the setURLSreamHandlerFactory() static method from the URL class. This is where FetchWhois directs new URL instances to the new WHOIS protocol handler, using the whoisUSHFactory described later. The constructor uses a StringBuffer to consolidate the array of command line arguments into a single String, and then uses the static encode() method of URLEncoder to properly format the data. Then, it creates an URL object with the new whois URL scheme. Finally, it opens a connection to the URL and receives the WHOIS data. The whoisUSHFactory Class: Registering the Protocol HandlerThe URL class uses a URLStreamHandlerFactory implementation to choose an appropriate protocol handler. In order to use the WHOIS protocol handler, you must implement the URLStreamHandlerFactory interface. The constructor should take a String that contains the scheme of the URL object being instantiated. whoisUSHFactory checks to ensure that the scheme is whois, and if so, returns an instance of the WHOIS Handler. Otherwise, it returns null. Running FetchWhoisCompile FetchWhois with javac and then try running it by using the following command. The program should print an HTML document that contains the same data as when you used the whois URL within HotJava. java FetchWhois internic.net HotJava will soon support dynamically downloaded protocol handlers, enabling a much more flexible use of this feature. Manually installing these extensions will continue to be a useful alternative. More on URLStreamHandlerFactoryThe URLStreamHandlerFactory class is a means of passing out specific protocol handlers for each supported protocol handler. In Listing 35.5, you used a custom factory called whoisUSHFactory. This factory supported only one scheme, whois. However, factories can be much more general, and can support both custom protocol handlers and those provided within the JDK. Listing 35.6 shows another application, ParseURL, which uses its own URLStreamHandlerFactory implementation. This application will take a series of URLs, including new URL schemes, as command line arguments and then print out how the URL class parses them. This demonstrates how the URL class deals with different forms of URLs. Listing 35.6 ParseURL.java
ParseURL also elucidates how the MalformedURLException is created for unknown schemes. If the factory being used with your application doesn't return a protocol handler for a scheme, any attempt to create an URL instance with such a scheme will throw a MalformedURLException. In ParseURL, however, you prevent this from occurring so that you can see how new URLs are parsed. ParseURL has three classes, ParseURL, ParseURLFactory, and DummyHandler. The first is the only public class and is used to invoke the application. The main() method within the ParseURL class sets the URLStreamHandlerFactory to your custom one, ParseURLFactory. It then iterates through the command line arguments, creating URL instances for each and then printing out the portions of each URL. The ParseURLFactory is your custom factory. It inspects the scheme of the URL instance to be created. If the scheme happens to be one of the standard schemes supported within the JDK, it returns the corresponding protocol handler. All of these protocol handlers within the JDK are contained within the package sun.net.www.protocol.scheme. If the scheme is not one of the standard ones, ParseURLFactory returns an instance of DummyHandler, rather than null. If null were returned, a MalformedURLException would be thrown if you attempted to create any URLs with non-standard schemes. The DummyHandler class does very little, as its name suggests. This class allows you to create URL instances for non-standard schemes. You can then parse such URLs with methods like getHost() and getFile() without having to create a protocol handler for each new scheme. However, DummyHandler does not implement any connection mechanism. Thus, you will not be able to obtain any data through non-standard URL instances that use the DummyHandler. To test your ParseURL application, first compile it with the Java compiler. Then execute it with the Java interpreter with one or more URLs as arguments. For instance, invoking it with: java ParseURL http://www.yahoo.com/ newscheme:newstuff returns the following information:
|
|
|
|