[ Pobierz całość w formacie PDF ]
.For example, consider the following call to the URL constructor:URL url = new URL("protocol://foo.bar.com/file.ext");The URL class parses only the protocol component; later, a call to the URL class's getContent() or openStream( ) method starts the machinery in motion.The URL class locates theappropriate protocol handler by looking in the protocol-package hierarchy.It then creates aninstance of the appropriate URLStreamHandler class.The URLStreamHandler is responsible for parsing the rest of the URL string, includinghostname and filename, and possibly an alternative port designation.This allows differentprotocols to have their own variations on the format of the URL specification string.Note that thisstep is skipped when a URL is constructed with the "protocol," "host," and "file" componentsspecified explicitly.If the protocol is straightforward, its URLStreamHandler class can let Javado the parsing and accept the default behavior.For this illustration, we'll assume that the URLstring requires no special parsing.(If we use a nonstandard URL with a strange format, we'reresponsible for parsing it ourselves, as we'll show shortly.)The URL object next invokes the handler's openConnection( ) method, prompting the handlerto create a new URLConnection to the resource.The URLConnection performs whatevercommunications are necessary to talk to the resource and begins to fetch data for the object.Atthat time, it also determines the MIME type of the incoming object data and prepares anInputStream to hand to the appropriate content handler.This InputStream must send "pure"data with all traces of the protocol removed.The URLConnection also locates an appropriate content handler in the content-handlerpackage hierarchy.The URLConnection creates an instance of a content handler; to put thecontent handler to work, the URLConnection's getContent( ) method calls the contenthandler's getContent( ) method.If this sounds confusing, it is: we have three getContent() methods calling each other in a chain.The newly created ContentHandler object thenacquires the stream of incoming data for the object by calling the URLConnection'sgetInputStream( ) method.(Recall that we acquired an InputStream in our x_tar contenthandler.) The content handler reads the stream and constructs an object from the data.Thisobject is then returned up the getContent( ) chain: from the content handler, theURLConnection, and finally the URL itself.Now our application has the desired object in itsgreedy little hands.To summarize, we create a protocol handler by implementing a URLStreamHandler class thatcreates specialized URLConnection objects to handle our protocol.The URLConnectionobjects implement the getInputStream( ) method, which provides data to a content handlerfor construction of an object.The base URLConnection class implements many of the methodswe need; therefore, our URLConnection needs to provide only the methods that generate thedata stream and return the MIME type of the object data.If you're not thoroughly confused by all that terminology (or even if you are), let's move on to theexample.It should help to pin down what all these classes are doing.A.2.3 The crypt HandlerIn this section, we'll build a crypt protocol handler.It parses URLs of the form:crypt:type://hostname[:port]/location/itemtype is an identifier that specifies what kind of encryption to use.The protocol itself is a simplifiedversion of HTTP; we'll implement the GET command and no more.We added the type identifierto the URL to show how to parse a nonstandard URL specification.Once the handler has figuredout the encryption type, it dynamically loads a class that implements the chosen encryptionalgorithm and uses it to retrieve the data.Obviously, we don't have room to implement a full-blown public-key encryption algorithm, so we'll use the rot13InputStream class from Chapter10.It should be apparent how the example can be extended by plugging in a more powerfulencryption class.A.2.3.1 The Encryption classFirst, we'll lay out our plug-in encryption class.We'll define an abstract class calledCryptInputStream that provides some essentials for our plug-in encrypted protocol.From theCryptInputStream we'll create a subclass called rot13CryptInputStream, thatimplements our particular kind of encryption://file: rot13CryptInputStream.javapackage learningjava.protocolhandlers.crypt;import java.io.*;abstract class CryptInputStream extends InputStream {InputStream in;OutputStream out;abstract public void set( InputStream in, OutputStream out );} // end of class CryptInputStreamclass rot13CryptInputStream extends CryptInputStream {public void set( InputStream in, OutputStream out ) {this.in = new learningjava.io.rot13InputStream( in );}public int read( ) throws IOException {return in.read( );}}Our CryptInputStream class defines a method called set( ) that passes in theInputStream it's to translate.Our URLConnection calls set( ) after creating an instance ofthe encryption class.We need a set( ) method because we want to load the encryption classdynamically, and we aren't allowed to pass arguments to the constructor of a class when it'sdynamically loaded.(We noticed this same issue in our content handler previously.) In theencryption class, we also provide for the possibility of an OutputStream.A more complex kindof encryption might use the OutputStream to transfer public-key information.Needless to say,rot13 doesn't, so we'll ignore the OutputStream here.The implementation of rot13CryptInputStream is very simple [ Pobierz całość w formacie PDF ]