Protocol handlers
• Handling
a protocol means taking care of the interaction between a client and a server:
generating requests in the correct format, interpreting the headers that come
back with the data, acknowledging that the data has been received.
• Java
divides the task of handling protocols into a number of pieces. As a result,
there is no single class called Protocol Handler. Instead, pieces of the
protocol handler mechanism are implemented by four different class es in the
java.net package: URL, URLStreamHandler, URLConnection, and
URLStreamHandlerFactory. URL is the only concrete class in this group.
• URLStreamHandler
and URLConnection are both abstract classes, and URLStreamHandlerFactory is an
interface. Therefore, if you are going to implement a new protocol handler, you
have to write concrete subclasses for the URLStreamHandler and the
URLConnection. To use these classes, you may also have to write a class that
implements the URLStreamHandlerFactory interface.
The sequence of events:
1. The
program constructs a URL object.
2. The
constructor uses the arguments it's passed to determine the protocol part of
the URL, e.g., http.
3. The URL(
) constructor tries to find a URLStreamHandler for the given protocol like
this:
a. If the
protocol has been used before, then the URLStreamHandler object is retrieved
from a cache.
b. Otherwise,
if a URLStreamHandlerFactory has been set, then the protocol string is passed
to the factory's createURLStreamHandler( ) method.
c. If the
protocol hasn't been seen before and there's no URlStream HandlerFactory, then
the constructor attempts to instantiate a URLStreamHandler object named
protocol.Handler
in one of the packages listed in the java.protocol.handler.pkgs property.
d. Failing
that, the constructor attempts to instantiate a URLStreamHandler object named
protocol.Handler in the sun.net.www.protocol package.
e. If any of
these attempts succeed in retrieving a URLStreamHandler object, the URL
constructor sets the URL object's handler field. If none of the attempts
f. succeed, the constructor throws a MalformedURLException.
4. The program calls the URL object's openConnection( ) method.
The URL
object asks the URLStreamHandler to return a URLConnection object appropriate
for this URL. If there's any problem, an IOException is thrown. Otherwise, a
URLConnection object is returned
6. The
program uses the methods of the URLConnection class to interact with the remote
resource.
Instead of calling openConnection( ) in step 4, the
program can call getContent( ) or getInputStream( ). In this case, the
URLStreamHandler still instantiates a URLConnection object of the appropriate
class. However, instead of returning the URLConnection object itself, the
URLStreamHandler returns the result of URLConnection's getContent( ) or
getInputStream( ) method.
URLStreamHandler Class
• The
abstract URLStreamHandler class is a superclass for classes that handle
specific protocols— for example, HTTP. We rarely call the methods of the
URLStreamHandler class directly; they are called by other methods in the URL
and URLConnection classes.
• By
overriding the URLStreamHandler methods in our own subclass, we teach the URL
class how to handle new protocols. Therefore, we'll focus on overriding the
methods of URLStreamHandler rather than on calling the methods.
Methods for Parsing URLs
• The first
responsibility of an URLStreamHandler is to split a string representation of a
URL into its component parts and use those parts to set the various fields of
the URL object.
• The
parseURL( ) method splits the URL into parts, possibly using setURL( ) to
assign values to the URL's fields. It is very difficult to imagine a situation
in which we would call parseURL( ) directly; instead, we override it to change
the behavior of the URL class.
Protected void parseURL(URL u,
String spec, int start, int limit)
• This
method parses a string spec into a URL u. All characters in the spec string
before start should already have been parsed into the URL u. Characters after
limit are ignored.
• The
protocol will have already been parsed and stored in u before this method is
invoked, and start will be adjusted so that it starts with the character after
the colon that delimits the protocol.
• The task
of parseURL( ) is to set the URL u's protocol, host, port, file, and ref
fields. It can assume that any parts of the String that are before start and
after limit have already been parsed or can be ignored. The parseURL( ) method
that Java supplies assumes that the URL looks more or less like an http URL:
protocol://www.host.com:port/directory/another_directory/file#ref
• This
works for ftp and gopher URLs. It does not work for mailto or news URLs and may
not be appropriate for any new URL types you define.
• If your
protocol handler uses URLs that fit this form, you don't have to override
parseURL( ) at all; the method inherited from URLStreamHandler will work just
fine. If your URLs are completely different, you must supply a parseURL( )
method that parses the URL completely. However, there's often a middle ground
that can make your task easier.
•
If your URL looks somewhat like a standard URL, you
can implement a parseURL( ) method that handles the nonstandard portion of your
URL and then calls super.parseURL( ) to do the rest of the work, setting the
offset and limit arguments to indicate the portion of the URL that you didn't
parse.
•
For example, a mailto URL looks like
mailto:elharo@metalab.unc.edu. First, you need to figure out how to map this
into the URL class's protocol, host, port, file, and ref fields. The protocol
is clearly mailto. Everything after the @ can be the host. The hard question is
what to do with the
username.
Since a mailto URL really doesn't have a file portion, we will use the URL
class's file field to hold the username. The ref can be set to the empty string
or null. The parseURL( ) method that follows implements this scheme:
public void parseURL(URL u, String spec, int start,
int limit) { String protocol = u.getProtocol( );
String
host = "";
int port
= u.getPort( );
String
file = ""; // really username
String
ref = null;
if( start
< limit) {
String
address = spec.substring(start, limit);
int
atSign = address.indexOf('@');
if
(atSign >= 0) {
host =
address.substring(atSign+1);
file =
address.substring(0, atSign);
}
}
this.setURL(u,
protocol, host, port, file, ref);
}
• Rather
than borrowing an unused field from the URL object, it's possibly a better idea
to store protocol-specific parts of the URL, such as the username, in fields of
the URLStreamHandler subclass.
• The
disadvantage of this approach is that such fields can be seen only by your own
code; in this example, you couldn't use the getFile( ) method in the URL class
to retrieve the username. Here's a version of parseURL( ) that stores the
username in a field of the Handler subclass.
• When the
connection is opened, the username can be copied into the Mailto URLConnection
object that results. That class would provide some sort of getUserName( )
method:
String
username = "";
public void parseURL(URL u, String spec, int start,
int limit) { String protocol = u.getProtocol( );
String
host = "";
int port
= u.getPort( );
String
file = "";
String
ref = null;
if( start
< limit) {
String
address = spec.substring(start, limit);
int
atSign = address.indexOf('@');
if
(atSign >= 0) {
host =
address.substring(atSign+1);
this.username
= address.substring(0, atSign);
}
}
this.setURL(u,
protocol, host, port, file, ref);
}
Method for Connecting
The second responsibility of a URLStreamHandler is
to create a URLConnection object appropriate to the URL. This is done by the
abstract openConnection( ) method.
Protected abstract URLConnection
openConnection(URL u) throws IOException
• This
method must be overridden in each subclass of URLConnection. It takes a single
argument u, which is the URL to connect to. It returns an unopened URLConnection,
directed at the resource u points to.
• Each
subclass of URLStreamHandler should know how to find the right subclass of
URLConnection for the protocol it handles. The openConnection( ) method is
protected, so you usually do not call it directly; it is called by the
openConnection( ) method of a URL class.
• The URL u
that is passed as an argument is the URL that needs a connection. You override
this method in your subclasses to handle a specific protocol. Your subclass's
openConnection( ) method is usually extremely simple; in most cases, it just
calls the constructor for the appropriate subclass of URLConnection.
For example, URLStreamHandler for the mailto protocol
might have an openConnection( ) method that looks like this:
protected URLConnection openConnection(URL u)
throws IOException { return new
com.macfaq.net.www.protocol.MailtoURLConnection(u);
}
Example
A mailto
URLStreamHandler
package
com.macfaq.net.www.protocol.mailto;
import
java.net.*;
import
java.io.*;
import
java.util.*;
public
class Handler extends URLStreamHandler {
protected URLConnection openConnection(URL u)
throws IOException {
return new MailtoURLConnection(u);
}
public
void parseURL(URL u, String spec, int start, int limit) {
String
protocol = u.getProtocol( );
String
host = "";
int port
= u.getPort( );
String
file = ""; // really username String userInfo = null;
String
authority = null; String query = null;
String
ref = null; if( start < limit) {
String
address = spec.substring(start, limit);
int
atSign = address.indexOf('@'); if (atSign >= 0) {
host =
address.substring(atSign+1);
file =
address.substring(0, atSign);
}
}
// For Java
1.2 comment out this next line this.setURL(u, protocol, host, port, authority,
userInfo, file, query, ref);
// In Java
1.2 and earlier uncomment the following line:
// this.setURL(u,
protocol, host, port, file, ref);
}
protected
String toExternalForm(URL u) {
return
"mailto:" + u.getFile() + "@" + u.getHost( );;
}
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.