A ContentHandlerFactory
defines the rules for
where ContentHandler
classes are stored. Create a
class that implements ContentHandlerFactory
, and
give this class a createContentHandler( )
method
that knows how to instantiate your ContentHandler
.
The createContentHandler( )
method should return
null
if it can’t find a
ContentHandler
appropriate for a MIME type;
null
signals Java to look for
ContentHandler
classes in the default locations.
When your application starts, call the
URLConnection
’s
setContentHandlerFactory( )
method to set the
ContentHandlerFactory
. This method may be called
only once in the lifetime of an application.
Just as the
createURLStreamHandler( )
method of the
URLStreamHandlerFactory
interface was responsible
for finding and loading the appropriate protocol handler, so too the
createContentHandler( )
method of the
ContentHandlerFactory
interface is responsible for
finding and loading the appropriate ContentHandler
given a MIME type:
public abstract ContentHandler createContentHandler(String mimeType)
This method should be called only by the getContent( )
method of a URLConnection
object. For
instance, Example 17.7 is a
ContentHandlerFactory
that knows how to find the
right handler for the text/tab-separated-values content handler of
Example 17.1:
Example 17-7. TabFactory
package com.macfaq.net.www.content; import java.net.*; public class TabFactory implements ContentHandlerFactory { public ContentHandler createContentHandler(String mimeType)) { if (mimeType.equals("text/tab-separated-values") { return new com.macfaq.net.www.content.text.tab_separated_values( ); } else { return null; // look for the handler in the default locations } } }
This factory knows how to find only one kind of content handler, but
there’s no limit to how many a factory can know about. For
example, this createContentHandler( )
method also
suggests handlers for application/x-time, text/plain, video/mpeg, and
model/vrml. Notice that when you’re using a
ContentHandlerFactory
, you don’t necessarily
have to stick to standard naming conventions for
ContentHandler
subclasses:
public ContentHandler createContentHandler(String mimeType)) { if (mimeType.equals("text/tab-separated-values") { return new com.macfaq.net.www.content.text.tab_separated_values( ); } else if (mimeType.equals("application/x-time") { return new com.macfaq.net.www.content.application.x_time( ); } else if (mimeType.equals("text/plain") { return new sun.net.www.content.text.plain( ); } if (mimeType.equals("video/mpeg") { return new com.macfaq.video.MPEGHandler( ); } if (mimeType.equals("model/vrml") { return new com.macfaq.threed.VRMLModel( ); } else { return null; // look for the handler in the default locations } }
A ContentHandlerFactory
is installed in an
application using the static
URLConnection.setContentHandlerFactory( )
method:
public static void setContentHandlerFactory(ContentHandlerFactory fac) throws SecurityException, Error
Note that this method is in the URLConnection
class, not the ContentHandler
class. It may be
invoked at most once during any run of an application. It throws an
Error
if it is called a second time.
Using a ContentHandlerFactory
such as the
TabFactory
in Example 17.5,
it’s possible to write a standalone application that can
automatically load our tab-separated-values content handler and that
runs in Java 1.1 through 1.3 without any major hassles with the class
path. Example 17.8 is such a program. However, as
with most other setFactory( )
methods, untrusted
applets will generally not be allowed to set the content handler
factory. Attempting to do so will throw a
SecurityException
. Consequently, installing new
content handlers in applets pretty much requires directly accessing
the getContent( )
method of the
ContentHandler
subclass itself. Ideally, this
shouldn’t be necessary, but until Sun provides better support
for downloadable content handlers in browsers, this is what
we’re stuck
with.
Example 17-8. TabLoader That Uses a ContentHandlerFactory
import java.io.*; import java.net.*; import java.util.*; import com.macfaq.net.www.content.*; public class TabLoader { public static void main (String[] args) { URLConnection.setContentHandlerFactory(new TabFactory( )); for (int i = 0; i < args.length; i++) { try { URL u = new URL(args[i]); Object content = u.getContent( ); Vector v = (Vector) content; for (Enumeration e = v.elements() ; e.hasMoreElements( ) ;) { String[] sa = (String[]) e.nextElement( ); for (int j = 0; j < sa.length; j++) { System.out.print(sa[j] + " "); } System.out.println( ); } } catch (MalformedURLException e) { System.err.println(args[i] + " is not a good URL"); } catch (Exception e) { e.printStackTrace( ); } } } }
Here’s a typical run. As usual, tabs are indicated by arrows:
% java TabLoader http://metalab.unc.edu/javafaq/addresses.tab
JPE Associates →341 Lafayette St, Suite 1025 →New York →NY →10012
O'Reilly & Associates →103 Morris St, Suite A →Sebastopol →CA →95472
3.147.89.24