The following lineListing 3-6.Using CookieHandler in Java 6 import java.io.*; import java.net.*; import java.util.*; public class Fetch { public static void mainString args[] throws Exce
Trang 1}}// Map to returnMap<String, List<String>> cookieMap =new HashMap<String, List<String>>(requestHeaders);
// Convert StringBuilder to List, store in map
if (cookies.length() > 0) {List<String> list =Collections.singletonList(cookies.toString());
cookieMap.put("Cookie", list);
}System.out.println("CookieMap: " + cookieMap);
// Make read-onlyreturn Collections.unmodifiableMap(cookieMap);
}}
In Java 6, the ListCookieHandlerturns into the CookieManagerclass The cookieJarthat
is used as the cache becomes the CookieStore One thing not in this implementation ofCookieHandleris a policy for storing cookies Do you want to accept no cookies, all cookies,
or only cookies from the original server? That’s where the CookiePolicyclass comes intoplay You will explore CookiePolicymore later
The last part of the Java 5 situation is the Cookieclass itself The constructor parsesout the fields from the header line Listing 3-5 shows an implementation that will bereplaced in Java 6 by HttpCookie The Java 6 version will also be more complete
Listing 3-5.Implementing a Cookie Class to Save for Java 5
Trang 2String domain;
Date expires;
String path;
private static DateFormat expiresFormat1
= new SimpleDateFormat("E, dd MMM yyyy k:m:s 'GMT'", Locale.US);
private static DateFormat expiresFormat2
= new SimpleDateFormat("E, dd-MMM-yyyy k:m:s 'GMT'", Locale.US);
public Cookie(URI uri, String header) {String attributes[] = header.split(";");
String nameValue = attributes[0].trim();
}String name = nameValue.substring(0, equals);
String value = nameValue.substring(equals+1);
if (name.equalsIgnoreCase("domain")) {String uriDomain = uri.getHost();
if (uriDomain.equals(value)) {this.domain = value;
} else {
if (!value.startsWith(".")) {value = "." + value;
}uriDomain = uriDomain.substring(uriDomain.indexOf('.'));
if (!uriDomain.equals(value)) {throw new IllegalArgumentException("Trying to set foreign cookie");
}this.domain = value;
}
C H A P T E R 3 ■ I / O, N E T W O R K I N G, A N D S E C U R I T Y U P D AT E S 49
Trang 3} else if (name.equalsIgnoreCase("path")) {this.path = value;
} else if (name.equalsIgnoreCase("expires")) {try {
this.expires = expiresFormat1.parse(value);} catch (ParseException e) {
try {this.expires = expiresFormat2.parse(value);} catch (ParseException e2) {
throw new IllegalArgumentException(
"Bad date format in header: " + value);}
}}}}
public boolean hasExpired() {
if (expires == null) {return false;
}Date now = new Date();
if (hasExpired()) {return false;
}
Trang 4String path = uri.getPath();
if (path == null) {path = "/";
}
return path.startsWith(this.path);
}public String toString() {StringBuilder result = new StringBuilder(name);
result.append("=");
result.append(value);
return result.toString();
}}
At this point, you can actually run the Fetch5program in Listing 3-3 To run theprogram, find a site that uses cookies and pass the URL string as the command-line
argument
> java Fetch5 http://java.sun.com
CookieMap: {Connection=[keep-alive], Host=[java.sun.com], User-Agent=[
Java/1.6.0-rc], GET / HTTP/1.1=[null], Content-type=[
application/x-www-form-urlencoded], Accept=[text/html, image/gif, image/jpeg,
*; q=.2, */*; q=.2]}
Cache: []
Adding to cache: SUN_ID=141.154.45.36:196601132578618
CookieMap: {Connection=[keep-alive], Host=[java.sun.com], User-Agent=[
Java/1.6.0-rc], GET / HTTP/1.1=[null], Cookie=[
SUN_ID=141.154.45.36:196601132578618], Content-type=[
application/x-www-form-urlencoded], Accept=[text/html, image/gif,image/jpeg, *; q=.2, */*; q=.2]}
Cache: [SUN_ID=141.154.45.36:196601132578618]
The first line shows the adjusted map from the get()call Since the cookie jar (cache)
is empty when the initial get()is called, there are no cookie lines added When the put()
happens, a Set-Cookieheader is found, so it is added to the cache The next request to
get()finds the cookie in the cache and adds the header to the adjusted map
C H A P T E R 3 ■ I / O, N E T W O R K I N G, A N D S E C U R I T Y U P D AT E S 51
Trang 5Now that you’ve seen the Java 5 way of caching cookies, let’s change Listing 3-3 andthe Fetch5program to the Java 6 way The following line
Listing 3-6.Using CookieHandler in Java 6
import java.io.*;
import java.net.*;
import java.util.*;
public class Fetch {
public static void main(String args[]) throws Exception {Console console = System.console();
if (args.length == 0) {System.err.println("URL missing");
System.exit(-1);
}String urlString = args[0];
CookieManager manager = new CookieManager();
CookieHandler.setDefault(manager);
URL url = new URL(urlString);
URLConnection connection = url.openConnection();
Object obj = connection.getContent();
url = new URL(urlString);
connection = url.openConnection();
obj = connection.getContent();
CookieStore cookieJar = manager.getCookieStore();
List<HttpCookie> cookies = cookieJar.getCookies();
for (HttpCookie cookie: cookies) {console.printf("Cookie: %s%n", cookie);
}}}
Trang 6One difference between the Java 5 version created and the Java 6 implementationprovided is that the CookieStorecache deals with the expiration of cookies This shouldn’t
be the responsibility of the handler (CookieManager) All the handler needs to do is tell the
cache to store something The fact that other cookies have expired shouldn’t matter to
the handler
Another difference is the CookiePolicyinterface (not yet shown) You can define acustom policy for dealing with cookies or tell the CookieManagerto use one of the prede-
fined ones The interface consists of a single method:
boolean shouldAccept(URI uri, HttpCookie cookie)
The interface also includes three predefined policies: ACCEPT_ALL, ACCEPT_NONE, andACCEPT_ORIGINAL_SERVER The last one will reject third-party cookies, accepting only those
that come from the original server—the same server as the response
To set the cookie policy for the CookieManager, call itssetCookiePolicy()method thefollowing:
CookieManager manager = new CookieManager();
manager.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(manager);
The CookieManagerclass also has a constructor that accepts a CookieStoreand aCookiePolicy:
public CookieManager(CookieStore store, CookiePolicy cookiePolicy)
Use this constructor if you want to use a cache other than the in-memoryCookieStoreused as a default (such as for long-term cookie storage between runs) You
cannot change the cache for the manager after creation, but you can change the
default-installed handler at any time
Besides the additional cookie support in standard Java, there is a new IDNclass forconverting internationalized domain names (IDNs) between an ASCII-compatible
encoding (ACE) and Unicode representation In addition, there is a new InterfaceAddress
class and new methods added to NetworkInterfacefor providing information about the
available network interfaces Listing 3-7 demonstrates the new methods added The
method names make the purpose of the methods pretty obvious, so no explanation is
Trang 7public class NetworkInfo {
public static void main(String args[]) throws SocketException {Console console = System.console();
Enumeration<NetworkInterface> nets =NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets)) {console.printf("Display name: %s%n",
netint.getDisplayName());
console.printf("Name: %s%n", netint.getName());
console.printf("Hardware address: %s%n",Arrays.toString(netint.getHardwareAddress()));
console.printf("Supports multicast? %s%n", netint.isVirtual());
List<InterfaceAddress> addrs = netint.getInterfaceAddresses();
for (InterfaceAddress addr : addrs) {console.printf("InterfaceAddress: %s - %s%n",addr.getAddress(), addr.getBroadcast());
}console.printf("%n");
}}}
Again, the results of running the program depend upon your system configuration.They’re similar to what you might see with an ipconfigcommand The physical address
is shown as a series of signed bytes More commonly, you would expect to see their hexvalues
Trang 8an SSLSocket, SSLEngine, or SSLContext.
The java.security Package
As Table 3-3 previously showed, there aren’t many added interfaces or classes in the
security packages The changes are related to some new methods added to the Policy
class The Policyclass now has a new marker interface, Policy.Parameters, for specifying
parameters when getting an instance A second marker interface is Configuration
Parametersin the javax.security.auth.loginpackage These marker interfaces are
imple-mented by the new URIParameterclass, which wraps a URIfor a Policyor Configuration
provider These are used internally by the PolicySpiand ConfigurationSpiclasses,
respec-tively, for what will become a familiar service provider lookup facility
Summary
Keeping to the concept of building up from the basic libraries to those that are a tad more
involved, in this chapter you looked at the I/O, networking, and security libraries These
packages stayed relatively unchanged The Fileclass finally has a free disk space API, and
you can also manipulate the read, write, and execute bits Cookie management is now
available in a much simpler form with Java 6 You could certainly do things yourself with
the API exposed in Java 5, but it is certainly easier the Mustang way Last, you explored
the new network interface to display newly available information
C H A P T E R 3 ■ I / O, N E T W O R K I N G, A N D S E C U R I T Y U P D AT E S 55
Trang 9The next chapter gets into some of the more visual new features of Mustang—those
of the java.awtand javax.swingpackages You saw how to access the system desktop inChapter 1 Chapter 4 teaches you about the new splash screen support, table sorting andfiltering, and system tray access
Trang 10AWT and Swing Updates
Have GUIs gotten better? Graphical user interfaces written with the Swing component
set seem to be on the rise since JDK 1.4 I’m not sure what triggered the change, but it
is no longer abnormal to see a full-fledged graphical program written from the ground
up with the Java programming language Just look at Sun’s Swing Connection at www
theswingconnection.comto see the latest things people are doing with Java-based
user interfaces Of the packages covered in this book so far, the AWT and Swing
packages have changed the most Table 4-1 shows the java.awtupdates, and Table 4-2
shows javax.swing’s changes
Table 4-1.java.awt.* Package Sizes
Trang 11Table 4-2.javax.swing.* Package Sizes
Package Version Interfaces Classes Enums Throwable Total
Trang 12Package Version Interfaces Classes Enums Throwable Total
classes have internal changes, like additional methods You’ll find no new components
added to either AWT or Swing, but plenty of changes to go around—all very visual
The java.awt Package
You’ll find the java.awtpackage growing to better integrate with the desktop
environ-ment In addition to the Desktopclass demonstrated in Chapter 1, you’ll find other areas
of the system environment exposed to the Java developer that were previously
unavail-able, as follows:
• Splash screen
• System tray
C H A P T E R 4 ■ AW T A N D S W I N G U P D AT E S 59
Trang 13The quick-and-dirty way of doing this is via the -splashcommand-line switch.java -splash:MyImage.jpg HelloSplash
What happens here is the MyImage.pngimage will show immediately, centered inthe screen Once your application creates a top-level window, the image goes away.Supported image formats include GIF, JPEG, and PNG, including their animated, trans-parent, and translucent varieties
It is that simple to do, though you typically don’t want to force the user to specify a -splashcommand-line switch every time they start up your program Instead, a betterway to work with splash screens is to specify the splash screen in the manifest of a JAR fileand jar up your application To demonstrate, Listing 4-1 is a simple program that directlydoes absolutely nothing with splash screens
Listing 4-1.Creating a Simple GUI Window with a Label
import javax.swing.*;
import java.awt.*;
public class HelloSplash {
public static void main(String args[]) {Runnable runner = new Runnable() {public void run() {
try {Thread.sleep(3000);
} catch (InterruptedException e) {}
Trang 14JFrame frame = new JFrame("Java 6 Revealed");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel(
" Java 6 Revealed", JLabel.CENTER);
frame.add(label, BorderLayout.CENTER);
frame.setSize(300, 95);
frame.setVisible(true);
}};
EventQueue.invokeLater(runner);
}}
Compile and run the program with the earlier command-line switch to make sureeverything works fine Be sure you have an image available to use as the splash screen
When the program is run, your image will show first (as in Figure 4-1), and then the
screen in Figure 4-2 will be shown
Figure 4-1.A splash screen of my dog, Jaeger
Figure 4-2.A simple graphical screen
To move this program into the world of JAR files, your manifest file needs to specifythe main class to execute and the name of the image to display as the splash screen The
main class is specified using the Main-Classidentifier, and the splash screen is specified
with SplashScreen-Image Create a file named manifest.mf, and place the contents of
Listing 4-2 in it Make corrections for the image name if you decide to name the image
differently, possibly due to a different image file format
C H A P T E R 4 ■ AW T A N D S W I N G U P D AT E S 61
Trang 15Listing 4-2.The Manifest File to Show the Splash Screen
Manifest-Version: 1.0
Main-Class: HelloSplash
SplashScreen-Image: MyImage.jpg
Next, package up the manifest file, class files, and image
jar -mcvf manifest.mf Splash.jar HelloSplash*.class MyImage.jpg
You can now run your program by passing the JAR file name to the java -jarcommand
java -jar Splash.jar
Notice that you don’t have to specify the -splashoption here anymore to see thesplash screen This is the typical way that splash screens will be packed up for users.For those interested in doing a little more with splash screens, you have access to thesplash screen area in your program when the runtime starts up, but before you createyour own window For instance, if you want to change the image to indicate some level
of progress, add a call to the setImageURL()method, as follows:
SplashScreen splash = SplashScreen.getSplashScreen();
URL url = ;
splash.setImageURL(url);
The image specified by the URL should be the same size as the original, since thesplash screen area doesn’t grow based upon the new image provided To find out its size,just ask with a call to getSize(), which returns a Dimensionobject There are no bordersaround the splash screen image, so it should be the size of the original image specified asthe splash screen
If you want to show a progress bar over the splash screen, a little extra work isinvolved You can think of the splash screen as a double-buffered image You get itsgraphics context with the createGraphics()method, draw to it, and then tell the splashscreen to update itself with its update()method Until update()is called, the user doesn’tsee the intermediate drawing operations So, for the “draw to it” part, you would draw agrowing rectangle The Graphicsobject returned from the createGraphics()method is aGraphics2Dobject, so more advanced graphics operations can be done For simplicity’ssake, Listing 4-3 only draws a growing white rectangle over the splash screen Considerchanging the color if white doesn’t work with your image