[ Pobierz całość w formacie PDF ]
.println( "GET " + url.getFile( ) );// Initialize the CryptInputStreamcis.set( s.getInputStream( ), server );connected = true;}public InputStream getInputStream( ) throws IOException {if (!connected)connect( );return ( cis );}}The constructor for our CryptURLConnection class takes as arguments the destination URLand the name of an encryption type.We pass the URL on to the constructor of our superclass,which saves it in a protected url instance variable.We could have saved the URL ourselves, butcalling our parent's constructor shields us from possible changes or enhancements to the baseclass.We use crypType to construct the name of an encryption class, using the convention thatthe encryption class is in the same package as the protocol handler (i.e.,learningjava.protocolhandlers.crypt); its name is the encryption type followed by thesuffix CryptInputStream.Once we have a name, we need to create an instance of the encryption class.To do so, we usethe static method Class.forName( ) to turn the name into a Class object andnewInstance( ) to load and instantiate the class.(This is how Java loads the content andprotocol handlers themselves.) newInstance( ) returns an Object; we need to cast it tosomething more specific before we can work with it.Therefore, we cast it to ourCryptInputStream class, the abstract class that rot13CryptInputStream extends.If weimplement any additional encryption types as extensions to CryptInputStream and namethem appropriately, they will fit into our protocol handler without modification.We do the rest of our setup in the connect( ) method of the URLConnection.There, wemake sure we have an encryption class and open a Socket to the appropriate port on theremote host.getPort( ) returns -1 if the URL doesn't specify a port explicitly; in that case weuse the default port for an HTTP connection (port 80).We ask for an OutputStream on thesocket, assemble a GET command using the getFile( ) method to discover the filenamespecified by the URL, and send our request by writing it into the OutputStream.(Forconvenience, we wrap the OutputStream with a PrintWriter and call println( ) to sendthe message.) We then initialize the CryptInputStream class by calling its set( ) methodand passing it an InputStream from the Socket and the OutputStream.The last thing connect( ) does is set the boolean variable connected to true.connected isa protected variable inherited from the URLConnection class.We need to track the state ofour connection because connect( ) is a public method.It's called by the URLConnection'sgetInputStream( ) method, but it could also be called by other classes.Since we don't wantto start a connection if one already exists, we check connected first.In a more sophisticated protocol handler, connect( ) would also be responsible for dealing withany protocol headers that come back from the server.In particular, it would probably stash anyimportant information it can deduce from the headers (e.g., MIME type, content length, timestamp) in instance variables, where it's available to other methods.At a minimum, connect( )strips the headers from the data so the content handler won't see them.I'm being lazy andassuming that we'll connect to a minimal server, like the modified TinyHttpd daemon wediscuss below, which doesn't bother with any headers.The bulk of the work has been done; a few details remain.The URLConnection'sgetContent( ) method needs to figure out which content handler to invoke for this URL.Inorder to compute the content handler's name, getContent( ) needs to know the resource'sMIME type.To find out, it calls the URLConnection's getContentType( ) method, whichreturns the MIME type as a String.Our protocol handler overrides getContentType( ),providing our own implementation.The URLConnection class provides a number of tools to help determine the MIME type.It'spossible that the MIME type is conveyed explicitly in a protocol header; in this case, a moresophisticated version of connect( ) would have stored the MIME type in a convenient locationfor us.Some servers don't bother to insert the appropriate headers, though, so you can use themethod guess-ContentTypeFromName( ) to examine filename extensions, like.gif or.html,and map them to MIME types.In the worst case, you can use guessContent-TypeFromStream( ) to intuit the MIME type from the raw data.The Java developers call thismethod "a disgusting hack" that shouldn't be needed, but that is unfortunately necessary in aworld where HTTP servers lie about content types and extensions are often nonstandard.We'lltake the easy way out and use the guessContentTypeFromName( ) utility of theURLConnection class to determine the MIME type from the filename extension of the URL weare retrieving.Once the URLConnection has found a content handler, it calls the content handler'sgetContent( ) method.The content handler then needs to get an InputStream from whichto read the data.To find an InputStream, it calls the URLConnection's getInputStream( )method.getInputStream( ) returns an InputStream from which its caller can read the dataafter protocol processing is finished.It checks whether a connection is already established; if not,it calls connect( ) to make the connection.Then it returns a reference to ourCryptInputStream.A final note on getting the content type: the URLConnection's default getContentType( )calls getHeaderField( ), which is presumably supposed to extract the named field from theprotocol headers (it would probably spit back information connect( ) had stored away) [ Pobierz całość w formacie PDF ]
zanotowane.pl doc.pisz.pl pdf.pisz.pl odbijak.htw.pl
.println( "GET " + url.getFile( ) );// Initialize the CryptInputStreamcis.set( s.getInputStream( ), server );connected = true;}public InputStream getInputStream( ) throws IOException {if (!connected)connect( );return ( cis );}}The constructor for our CryptURLConnection class takes as arguments the destination URLand the name of an encryption type.We pass the URL on to the constructor of our superclass,which saves it in a protected url instance variable.We could have saved the URL ourselves, butcalling our parent's constructor shields us from possible changes or enhancements to the baseclass.We use crypType to construct the name of an encryption class, using the convention thatthe encryption class is in the same package as the protocol handler (i.e.,learningjava.protocolhandlers.crypt); its name is the encryption type followed by thesuffix CryptInputStream.Once we have a name, we need to create an instance of the encryption class.To do so, we usethe static method Class.forName( ) to turn the name into a Class object andnewInstance( ) to load and instantiate the class.(This is how Java loads the content andprotocol handlers themselves.) newInstance( ) returns an Object; we need to cast it tosomething more specific before we can work with it.Therefore, we cast it to ourCryptInputStream class, the abstract class that rot13CryptInputStream extends.If weimplement any additional encryption types as extensions to CryptInputStream and namethem appropriately, they will fit into our protocol handler without modification.We do the rest of our setup in the connect( ) method of the URLConnection.There, wemake sure we have an encryption class and open a Socket to the appropriate port on theremote host.getPort( ) returns -1 if the URL doesn't specify a port explicitly; in that case weuse the default port for an HTTP connection (port 80).We ask for an OutputStream on thesocket, assemble a GET command using the getFile( ) method to discover the filenamespecified by the URL, and send our request by writing it into the OutputStream.(Forconvenience, we wrap the OutputStream with a PrintWriter and call println( ) to sendthe message.) We then initialize the CryptInputStream class by calling its set( ) methodand passing it an InputStream from the Socket and the OutputStream.The last thing connect( ) does is set the boolean variable connected to true.connected isa protected variable inherited from the URLConnection class.We need to track the state ofour connection because connect( ) is a public method.It's called by the URLConnection'sgetInputStream( ) method, but it could also be called by other classes.Since we don't wantto start a connection if one already exists, we check connected first.In a more sophisticated protocol handler, connect( ) would also be responsible for dealing withany protocol headers that come back from the server.In particular, it would probably stash anyimportant information it can deduce from the headers (e.g., MIME type, content length, timestamp) in instance variables, where it's available to other methods.At a minimum, connect( )strips the headers from the data so the content handler won't see them.I'm being lazy andassuming that we'll connect to a minimal server, like the modified TinyHttpd daemon wediscuss below, which doesn't bother with any headers.The bulk of the work has been done; a few details remain.The URLConnection'sgetContent( ) method needs to figure out which content handler to invoke for this URL.Inorder to compute the content handler's name, getContent( ) needs to know the resource'sMIME type.To find out, it calls the URLConnection's getContentType( ) method, whichreturns the MIME type as a String.Our protocol handler overrides getContentType( ),providing our own implementation.The URLConnection class provides a number of tools to help determine the MIME type.It'spossible that the MIME type is conveyed explicitly in a protocol header; in this case, a moresophisticated version of connect( ) would have stored the MIME type in a convenient locationfor us.Some servers don't bother to insert the appropriate headers, though, so you can use themethod guess-ContentTypeFromName( ) to examine filename extensions, like.gif or.html,and map them to MIME types.In the worst case, you can use guessContent-TypeFromStream( ) to intuit the MIME type from the raw data.The Java developers call thismethod "a disgusting hack" that shouldn't be needed, but that is unfortunately necessary in aworld where HTTP servers lie about content types and extensions are often nonstandard.We'lltake the easy way out and use the guessContentTypeFromName( ) utility of theURLConnection class to determine the MIME type from the filename extension of the URL weare retrieving.Once the URLConnection has found a content handler, it calls the content handler'sgetContent( ) method.The content handler then needs to get an InputStream from whichto read the data.To find an InputStream, it calls the URLConnection's getInputStream( )method.getInputStream( ) returns an InputStream from which its caller can read the dataafter protocol processing is finished.It checks whether a connection is already established; if not,it calls connect( ) to make the connection.Then it returns a reference to ourCryptInputStream.A final note on getting the content type: the URLConnection's default getContentType( )calls getHeaderField( ), which is presumably supposed to extract the named field from theprotocol headers (it would probably spit back information connect( ) had stored away) [ Pobierz całość w formacie PDF ]