FileDocCategorySizeDatePackage
HttpGet.javaAPI DocExample6190Sat Jan 24 10:44:28 GMT 2004je3.nio

HttpGet

public class HttpGet extends Object

Fields Summary
Constructors Summary
Methods Summary
public static voidmain(java.lang.String[] args)

	SocketChannel server = null;        // Channel for reading from server
	FileOutputStream outputStream = null;  // Stream to destination file
	WritableByteChannel destination;       // Channel to write to it

	try { // Exception handling and channel closing code follows this block

	    // Parse the URL. Note we use the new java.net.URI, not URL here.
	    URI uri = new URI(args[0]);

	    // Now query and verify the various parts of the URI
	    String scheme = uri.getScheme();
	    if (scheme == null || !scheme.equals("http"))
	       throw new IllegalArgumentException("Must use 'http:' protocol");

	    String hostname = uri.getHost();

	    int port = uri.getPort();
	    if (port == -1) port = 80; // Use default port if none specified

	    String path = uri.getRawPath();
	    if (path == null || path.length() == 0) path = "/";

	    String query = uri.getRawQuery();
	    query = (query == null)?"":'?"+query;

	    // Combine the hostname and port into a single address object.
	    // java.net.SocketAddress and InetSocketAddress are new in Java 1.4
	    SocketAddress serverAddress=new InetSocketAddress(hostname, port);

	    // Open a SocketChannel to the server
	    server = SocketChannel.open(serverAddress);

	    // Put together the HTTP request we'll send to the server.
	    String request =
		"GET " + path + query + " HTTP/1.1\r\n" +  // The request
		"Host: " + hostname + "\r\n" +   // Required in HTTP 1.1
		"Connection: close\r\n" +        // Don't keep connection open
		"User-Agent: " + HttpGet.class.getName() + "\r\n" +
		"\r\n";  // Blank line indicates end of request headers

	    // Now wrap a CharBuffer around that request string
	    CharBuffer requestChars = CharBuffer.wrap(request);

	    // Get a Charset object to encode the char buffer into bytes
	    Charset charset = Charset.forName("ISO-8859-1");
	    
	    // Use the charset to encode the request into a byte buffer
	    ByteBuffer requestBytes = charset.encode(requestChars);

	    // Finally, we can send this HTTP request to the server.
	    server.write(requestBytes);

	    // Set up an output channel to send the output to.
	    if (args.length > 1) {   // Use a specified filename
		outputStream = new FileOutputStream(args[1]);
		destination = outputStream.getChannel();
	    }
	    else                    // Or wrap a channel around standard out
		destination = Channels.newChannel(System.out);

	    // Allocate a 32 Kilobyte byte buffer for reading the response.  
	    // Hopefully we'll get a low-level "direct" buffer
	    ByteBuffer data = ByteBuffer.allocateDirect(32 * 1024);
	    
	    // Have we discarded the HTTP response headers yet?
	    boolean skippedHeaders = false;
	    // The code sent by the server
	    int responseCode = -1;

	    // Now loop, reading data from the server channel and writing it 
	    // to the destination channel until the server indicates that it
	    // has no more data.
	    while(server.read(data) != -1) {  // Read data, and check for end
		data.flip();      // Prepare to extract data from buffer

		// All HTTP reponses begin with a set of HTTP headers, which
		// we need to discard.  The headers end with the string
		// "\r\n\r\n", or the bytes 13,10,13,10.  If we haven't already
		// skipped them then do so now.
		if (!skippedHeaders) {
		    // First, though, read the HTTP response code.
		    // Assume that we get the complete first line of the
		    // response when the first read() call returns. Assume also
		    // that the first 9 bytes are the ASCII characters
		    // "HTTP/1.1 ", and that the response code is the ASCII
		    // characters in the following three bytes.
		    if (responseCode == -1) {
			responseCode =
			    100 * (data.get(9)-'0") +
			    10 * (data.get(10)-'0") +
			    1 * (data.get(11)-'0");
			
			// If there was an error, report it and quit
			// Note that we do not handle redirect responses.
			if (responseCode < 200 || responseCode >= 300) {
			    System.err.println("HTTP Error: " + responseCode);
			    System.exit(1);
			}
		    }
		    
		    // Now skip the rest of the headers.
		    try {
			for(;;) {
			    if ((data.get() == 13) && (data.get() == 10) &&
				(data.get() == 13) && (data.get() == 10)) {
				skippedHeaders = true;
				break;
			    }
			}
		    }
		    catch (BufferUnderflowException e) {
			// If we arrive here, it means we reached the end of
			// the buffer and didn't find the end of the headers.
			// There is a chance that the last 1, 2, or 3 bytes in
			// the buffer were the beginning of the \r\n\r\n
			// sequence, so back up a bit.
			data.position(data.position()-3);
			// Now discard the headers we have read
			data.compact();
			// And go read more data from the server.
			continue;
		    }
		}

		// Write the data out; drain the buffer fully.
		while(data.hasRemaining()) destination.write(data);

		// Now that the buffer is drained, put it into fill mode
		// in preparation for reading more data into it.
		data.clear();      // data.compact() also works here
	    }
	}
        catch (Exception e) {    // Report any errors that arise
            System.err.println(e);
            System.err.println("Usage: java HttpGet <URL> [<filename>]");
        }
	finally { // Close the channels and output file stream, if needed
	    try {
		if (server != null && server.isOpen()) server.close();
		if (outputStream != null) outputStream.close();
	    }
	    catch(IOException e) {}
	}