Configuring the Connection

The URLConnection class has seven protected instance fields that define exactly how the client will make the request to the server. These are:

protected URL     url;
protected boolean doInput = true;
protected boolean doOutput = false;
protected boolean allowUserInteraction = defaultAllowUserInteraction;
protected boolean useCaches = defaultUseCaches;
protected long    ifModifiedSince = 0;
protected boolean connected = false;

For instance, if doOutput is true, then you’ll be able to write data to the server over this URLConnection as well as read data from it. If useCaches is false, the connection will bypass any local caching and download the file from the server afresh.

Since these fields are all protected, their values are accessed and modified via obviously named setter and getter methods:

public URL     
            getURL(  )
public void    setDoInput(boolean doInput)
public boolean getDoInput(  )
public void    
            
            setDoOutput(boolean doOutput)
public boolean getDoOutput(  )
public void    setAllowUserInteraction(boolean allowUserInteraction)
public boolean getAllowUserInteraction(  )
public void    
            
            
            setUseCaches(boolean useCaches)
public boolean getUseCaches(  )
public void    setIfModifiedSince(long ifModifiedSince)
public long    getIfModifiedSince(  )

You can modify these fields only before the URLConnection is connected (that is, before you try to read content or headers from the connection). Most of the methods that set fields throw an IllegalAccessError if they are called while the connection is open. In general, you can set the properties of a URLConnection object only before the connection is opened.

Note

Throwing an error instead of an exception here is very unusual. An error generally indicates an unpredictable, generally unhandleable fault in the VM, whereas an exception indicates a predictable, manageable problem. More specifically, a java.lang.IllegalAccessError is supposed to indicate that an application is trying to access a nonpublic field it doesn’t have access to. According to the class library documentation, “Normally, this error is caught by the compiler; this error can only occur at run time if the definition of a class has incompatibly changed.” Clearly, that’s not what’s going on here. This is simply a mistake on the part of the programmer who wrote this class.

A better solution here would be to throw an IllegalStateException or some other runtime exception. Sun has acknowledged the problem—it’s bug #4082758 in the Bug Parade on the Java Developer Connection at http://developer.java.sun.com/developer/bugParade/index.html—however, they have not yet fixed it, nor apparently do they have any plans to fix it in future releases.

There are also some private static fields that define the default behavior for all instances of URLConnection. These are:

private static boolean     defaultAllowUserInteraction = false;
private static boolean     defaultUseCaches = true;
private static FileNameMap fileNameMap;

These fields are also accessed and modified via obviously named setter and getter methods:

public boolean            
            
            getDefaultUseCaches(  )
public void               setDefaultUseCaches(boolean defaultUseCaches)
public static void        setDefaultAllowUserInteraction(
 boolean defaultAllowUserInteraction)
public static boolean     
            
            
            getDefaultAllowUserInteraction(  )
public static FileNameMap getFileNameMap(  )
public static void        setFileNameMap(FileNameMap map)

Unlike the instance fields, these fields can be changed at any time. The new defaults will apply only to URLConnection objects constructed after the new default values are set.

protected URL url

The url field specifies the URL that this URLConnection connects to. It is set by the constructor when the URLConnection is created and should not change. You can retrieve the value by calling the getURL( ) method. Example 15.5 opens a URLConnection to http://www.oreilly.com/, gets the URL of that connection, and prints it.

Example 15-5. Print the URL of a URLConnection to http://www.oreilly.com/

import java.net.*;
import java.io.*;

public class URLPrinter {

  public static void main(String args[]) {

    try {
      URL u = new URL("http://www.oreilly.com/");
      URLConnection uc = u.openConnection(  );
      System.out.println(uc.getURL(  ));
    }
    catch (IOException e) {
      System.err.println(e);
    }

  }

}

Here’s the result, which should be no great surprise. The URL that is printed is the one used to create the URLConnection.

% java URLPrinter
http://www.oreilly.com/

connected

The boolean field connected is true if the connection is open and false if it’s closed. Since the connection has not yet been opened when a new URLConnection object is created, its initial value is false. This variable can be accessed only by instances of java.net.URLConnection and its subclasses.

There are no methods that directly read or change the value of connected. However, any method that causes the URLConnection to connect should set this variable to true. This includes connect( ), getInputStream( ), and getOutputStream( ). Any method that causes the URLConnection to disconnect should set this field to false. There are no such methods in java.net.URLConnection, but some of its subclasses, such as java.net.HttpURLConnection, have disconnect( ) methods.

If you subclass URLConnection to write a protocol handler, you are responsible for setting connected to true when you are connected and resetting it to false when the connection closes. Many methods in java.net.URLConnection read this variable to determine what they can do. If it’s set incorrectly, your program will have severe bugs that are not easy to diagnose.

allowUserInteraction

Some URLConnections need to interact with a user. For example, a web browser may need to ask for a username and password. However, many applications cannot assume that a user is present to interact with it. For instance, a search engine robot is probably running in the background without any user to provide a username and password. As its name suggests, the allowUserInteraction field specifies whether user interaction is allowed. It is false by default.

Since this variable is protected, you use the public getAllowUserInteraction( ) method to read its value, and the public setAllowUserInteraction( ) method to set it:

public void setAllowUserInteraction(boolean allowUserInteraction)
 throws IllegalAccessError
public boolean getAllowUserInteraction(  )

The value true indicates that user interaction is allowed; false indicates that there is no user interaction. The value may be read at any time but may be set only when the connection is closed. Calling setAllowUserInteraction( ) when the connection is open throws an IllegalAccessError. Programs usually don’t catch errors (unlike exceptions); an uncaught error usually forces the program to terminate.

Example 15.6 creates a new HttpURLConnection, uses getAllowUserInteraction( ) to see whether user interaction is allowed, and, if it isn’t, uses setAllowUserInteraction( ) to allow user interaction. Of the major standalone VMs, only Apple’s Macintosh Runtime for Java will pop up an authentication dialog box in a standalone application like Example 15.6, even when allowUserInteraction is true. Specifically, Sun’s JDK on Windows and Unix will not ask the user for authentication unless you’ve installed an Authenticator as was discussed in Chapter 7. Unfortunately, this class is available only in Java 1.2 and later. However, most web browsers will ask if allowUserInteraction is true and the request is made from inside an applet.

Note

You actually can get Sun’s JDK to pop up an authentication dialog in Java 1.1, but you have to use undocumented methods in sun.net.www.protocol.http.HttpURLConnection and sun.net.www.protocol.http.HttpAuthenticator classes to do so.

Example 15-6. A URLConnection That’s Allowed to Interact with the User If Necessary

import java.net.*;
import java.io.*;
import java.awt.*;


public class PasswordedPageViewer {

  public static void main(String[] args) {

    for (int i = 0; i < args.length; i++) {
      try {
        URL u = new URL(args[i]);
        URLConnection uc = u.openConnection(  );
        uc.setAllowUserInteraction(true);
        InputStream in = uc.getInputStream(  );
        Reader r = new InputStreamReader(in);
        int c;
        while ((c = r.read(  )) != -1) {
          System.out.print((char) c);
        } 
        System.out.println(  );
      }
      catch (IOException e) {
        System.err.println(e);
      }
      
    }
    
  }

}

Figure 15.1 shows the dialog box that pops up when you try to access a passwordsprotected page. If you cancel this dialog, you’ll get 401 Authorization Required error and whatever text the server sends to unauthorized users. However, if you refuse to send authorization at all, which you can do by pressing OK, then answering No when asked if you want to retry authorization, getInputStream( ) will throw a ProtocolException.

An authentication dialog box

Figure 15-1. An authentication dialog box

defaultAllowUserInteraction

The static defaultAllowUserInteraction field determines whether URLConnection objects whose setAllowUserInteraction( ) method is not explicitly invoked are allowed to pop up dialogs or otherwise interact with the user. It may be read by calling the public method getDefaultAllowUserInteraction( ) and set by calling the public method setDefaultAllowUserInteraction( ). Since this field is static (i.e., a class variable instead of an instance variable), setting it changes the default behavior for all instances of the URLConnection class that are created after setDefaultAllowUserInteraction( ) is called.

For instance, the following code fragment checks to see whether user interaction is allowed by default with getDefaultAllowUserInteraction( ). If user interaction is not allowed by default, the code uses setDefaultAllowUser-Interaction( ) to make allowing user interaction the default behavior.

if (!URLConnection.getDefaultAllowUserInteraction(  )) {
  URLConnection.setDefaultAllowUserInteraction(true);
}

doInput

Most URLConnection objects provide input to a client program. For example, a connection to a web server with the GET method would produce input for the client. However, a connection to a web server with the POST method might not. A URLConnection can be used for input to the program, output from the program, or both. The protected boolean field doInput is true if the URLConnection can be used for input, false if it cannot be. The default is true. To access this protected variable, use the public getDoInput( ) and setDoInput( ) methods:

public void    setDoInput(boolean doInput)
public boolean getDoInput(  )

For example:

try {
  URL u = new URL("http://www.oreilly.com");
  URLConnection uc = u.openConnection(  );
  if (!uc.getDoInput(  )) {
    uc.setDoInput(true);
  }
  // read from the connection...
catch (IOException e) {
  System.err.println(e);
}

doOutput

Programs can use a URLConnection to send output back to the server. For example, a program that needs to send data to the server using the POST method could do so by getting an output stream from a URLConnection. The protected boolean field doOutput is true if the URLConnection can be used for output, false if it cannot be; it is false by default. To access this protected variable, use the getDoOutput( ) and setDoOutput( ) methods:

public void    setDoOutput(boolean dooutput)
public boolean getDoOutput(  )

For example:

try {
  URL u = new URL("http://www.oreilly.com");
  URLConnection uc = u.openConnection(  );
  if (!uc.getDoOutput(  )) {
    uc.setDoOutput(true);
  }
  // write to the connection...
catch (IOException e) {
  System.err.println(e);
}

When you set doOutput to true for an http URL, the request method is changed from GET to POST. In Chapter 7, you saw how to send data to CGI programs with GET. GET is straightforward to work with, but it does limit the amount of data you can send. Some web servers have maximum numbers of characters they’ll accept as part of a GET request, typically 255 or 1,024. This is generally enough for a simple search request or page navigation, but not enough for a form that allows journalists to submit articles, for example. Forms that allow larger blocks of text should use POST instead. We’ll explore this more below when we talk about writing data to a server.

ifModifiedSince

Many clients, especially web clients, keep caches of previously retrieved documents. If the user asks for the same document again, it can be retrieved from the cache. However, it may have changed on the server since it was last retrieved. The only way to tell is to ask the server. Clients can include an If-modified-since in the client request MIME header. This header includes a date and time. If the document has changed since that time, the server should send it. Otherwise, it should not. Typically, this time is the last time the client fetched the document. For example, this client request says the document should be returned only if it has changed since 7:22:07 A.M., October 31, 1999, Greenwich Mean Time:

GET / HTTP 1.1
User-Agent: Java1.3beta
Host: login.metalab.unc.edu:56452
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: close
If-Modified-Since: Sun, 31 Oct 1999 19:22:07 GMT

If the document has changed since that time, the server will send it as usual. Otherwise, it will reply with a 304 Not Modified message like this:

HTTP 1.0 304 Not Modified
Server: WN/1.15.1
Date: Mon, 01 Nov 1999 16:26:16 GMT
Last-modified: Fri, 29 Oct 1999 23:40:06 GMT

The client will then load the document from its cache. Not all web servers respect the If-modified-since field. Some will send the document whether it’s changed or not.

The ifModifiedSince field in the URLConnection class specifies the date (in milliseconds since midnight, Greenwich Mean Time, January 1, 1970), which will be placed in the If-modified-since MIME header field. Because ifModifiedSince is protected, programs should call the getIfModifiedSince( ) and setIfModifiedSince( ) methods to read or modify it:

public long getIfModifiedSince(  )
public void setIfModifiedSince(long ifModifiedSince)

Example 15.7 prints the default value of ifModifiedSince, sets its value to 24 hours ago, and prints the new value. It then downloads and displays the document but only if it’s been modified in the last 24 hours.

Example 15-7. Set ifModifiedSince to 24 Hours Prior to Now

import java.net.*;
import java.io.*;
import java.util.*;

public class Last24 {

  public static void main (String[] args) {

    // Initialize a Date object with the current date and time
    Date today = new Date(  );
    long millisecondsPerDay = 24 * 60 * 60 * 1000;

    for (int i = 0; i < args.length; i++) {
      try {
        URL u = new URL(args[i]);
        URLConnection uc = u.openConnection(  );
        System.out.println("Will retrieve file if it's modified since "
         + new Date(uc.getIfModifiedSince(  )));
        uc.setIfModifiedSince((new Date(today.getTime(  ) 
          - millisecondsPerDay)).getTime(  ));
        System.out.println("Will retrieve file if it's modified since "
         + new Date(uc.getIfModifiedSince(  )));
        InputStream in = new BufferedInputStream(uc.getInputStream(  ));
        Reader r = new InputStreamReader(in);
        int c;
        while ((c = r.read(  )) != -1) {
          System.out.print((char) c);
        } 
        System.out.println(  );
        
      }
      catch (Exception e) {
        System.err.println(e);
      }
    }

  }

}

Here’s the result. First, we see the default value: midnight, January 1, 1970, GMT, converted to Pacific Standard Time. Next, we see the new time, which we set to 24 hours prior to the current time:

% java Last24 http://www.oreilly.com
Will retrieve file if it's been modified since Wed Dec 31 16:00:00 PST 1969
Will retrieve file if it's been modified since Sun Oct 31 11:17:04 PST 1999

Since this document hasn’t changed in the last 24 hours, it is not reprinted.

useCaches

Some clients, notably web browsers, can retrieve a document from a local cache, rather than retrieving it from a server. The useCaches variable determines whether a cache will be used if it’s available. The default value is true, meaning that the cache will be used; false means the cache won’t be used. Because useCaches is protected, programs access it using the getUseCaches( ) and setUseCaches( ) methods:

public void    setUseCaches(boolean useCaches)
public boolean getUseCaches(  )

This code fragment disables caching to ensure that the most recent version of the document is retrieved:

try {
  URL u = new URL("http://www.sourcebot.com/sourcebot/");
  URLConnection uc = u.openConnection(  );
  if (uc.getUseCaches(  )) {
    uc.setUseCaches(false);
  }
}
catch (IOException e) {
  System.err.println(e);
}

defaultUseCaches

defaultUseCaches defines the initial value of the useCaches field. defaultUseCaches can be read and modified by the public getDefaultUseCaches( ) and setDefaultUseCaches( ) methods:

public void    setDefaultUseCaches(boolean useCaches)
public boolean getDefaultUseCaches(  )

Since this variable is static (i.e., a class variable instead of an instance variable), setting it changes the default behavior for all instances of the URLConnection class created after the change. The next code fragment disables caching by default; after this code runs, URLConnections that want caching must enable it explicitly using setUseCaches(true).

if (uc.getDefaultUseCaches(  )) {
  uc.setDefaultUseCaches(false);
}
               
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.82.23