AhmadLang / Java, How To Program, 2004
.pdf
[Page 1108 (continued)]
24.2. Manipulating URLs
The Internet offers many protocols. The Hypertext Transfer Protocol (HTTP), which forms the basis of the World Wide Web, uses URIs (Uniform Resource Identifiers) to identify data on the Internet. URIs that specify the locations of documents are called URLs (Uniform Resource Locators). Common URLs refer to files or directories and can reference objects that perform complex tasks, such as database lookups and Internet searches. If you know the HTTP URL of a publicly available HTML document anywhere on the Web, you can access it through HTTP.
Java makes it easy to manipulate URLs. When you use a URL that refers to the exact location of a resource (e.g., a Web page) as an argument to the showDocument method of interface
AppletContext, the browser in which the applet is executing will display that resource. The applet in Fig. 24.1 and Fig. 24.2 demonstrates simple networking capabilities. It enables the user to select a Web page from a JList and causes the browser to display the corresponding page. In this example, the networking is performed by the browser.
[Page 1109]
Figure 24.1. HTML document to load SiteSelector applet.
1<html>
2<title>Site Selector</title>
3<body>
4 |
<applet code = |
"SiteSelector.class" width = "300" height = "75"> |
||||||||
5 |
<param |
name |
= |
"title0" |
value |
= |
"Java Home Page"> |
|||
6 |
<param |
name |
= |
"location0" |
value |
= |
"http://java.sun.com/"> |
|||
7 |
<param |
name |
= "title1" |
value |
= |
"Deitel"> |
||||
8 |
<param |
name |
= |
"location1" |
value |
= |
"http://www.deitel.com/"> |
|||
9<param name = "title2" value = "JGuru">
10<param name = "location2" value = "http://www.jGuru.com/">
11<param name = "title3" value = "JavaWorld">
12<param name = "location3" value = "http://www.javaworld.com/">
13</applet>
14</body>
15</html>
Figure 24.2. Loading a document from a URL into a browser.
(This item is displayed on pages 1110 - 1112 in the print version)
1 // Fig. 24.2: SiteSelector.java
2 // This program loads a document from a URL.
3import java.net.MalformedURLException;
4import java.net.URL;
5import java.util.HashMap;
6import java.util.ArrayList;
7import java.awt.BorderLayout;
8import java.applet.AppletContext;
9import javax.swing.JApplet;
10import javax.swing.JLabel;
11import javax.swing.JList;
12import javax.swing.JScrollPane;
13import javax.swing.event.ListSelectionEvent;
14import javax.swing.event.ListSelectionListener;
16public class SiteSelector extends JApplet
17{
18private HashMap< Object, URL > sites; // site names and URLs
19private ArrayList< String > siteNames; // site names
20private JList siteChooser; // list of sites to choose from
22// read HTML parameters and set up GUI
23public void init()
24{
25sites = new HashMap< Object, URL >(); // create HashMap
26siteNames = new ArrayList< String >(); // create ArrayList
28// obtain parameters from HTML document
29 |
getSitesFromHTMLParameters(); |
30 |
|
31// create GUI components and layout interface
32add( new JLabel( "Choose a site to browse" ), BorderLayout.NORTH );
34siteChooser = new JList( siteNames.toArray() ); // populate JList
35siteChooser.addListSelectionListener(
36new ListSelectionListener() // anonymous inner class
37{
38 |
// go to site user selected |
||
39 |
public void valueChanged( ListSelectionEvent event ) |
||
40 |
{ |
|
|
41 |
// get selected site name |
||
42 |
Object object |
= siteChooser.getSelectedValue(); |
|
43 |
|
|
|
44 |
// use site name to locate corresponding URL |
||
45 |
URL |
newDocument = sites.get( object ); |
|
46 |
|
|
|
47 |
// |
get applet |
container |
48 |
AppletContext |
browser = getAppletContext(); |
|
49 |
|
|
|
50 |
// tell applet container to change pages |
||
51 |
browser.showDocument( newDocument ); |
||
52 |
} // end method |
valueChanged |
|
53} // end anonymous inner class
54); // end call to addListSelectionListener
56add( new JScrollPane( siteChooser ), BorderLayout.CENTER );
57} // end method init
59// obtain parameters from HTML document
60private void getSitesFromHTMLParameters()
61{
62String title; // site title
63String location; // location of site
64URL url; // URL of location
65int counter = 0; // count number of sites
67title = getParameter( "title" + counter ); // get first site title
69// loop until no more parameters in HTML document
70while ( title != null )
71{
72// obtain site location
73location = getParameter( "location" + counter );
75try // place title/URL in HashMap and title in ArrayList
76{
77 |
url = new URL( |
location |
); |
// convert location to |
URL |
78 |
sites.put( title, url ); // put title/URL in HashMap |
||||
79 |
siteNames.add( |
title ); |
// |
put title in ArrayList |
|
80} // end try
81catch ( MalformedURLException urlException )
82{
83 |
urlException.printStackTrace(); |
84 |
} // end catch |
85 |
|
86counter++;
87title = getParameter( "title" + counter ); // get next site title
88} // end while
89} // end method getSitesFromHTMLParameters
90} // end class SiteSelector
[View full size image]
This applet takes advantage of applet parameters specified in the HTML document that invokes the applet. When browsing the World Wide Web, you will often come across applets that are in the public domainyou can use them free of charge on your own Web pages (normally in exchange for crediting the applet's creator). Many applets can be customized via parameters supplied from the HTML file that invokes the applet. For example, Fig. 24.1 contains the HTML that invokes the applet SiteSelector in Fig. 24.2.
The HTML document contains eight parameters specified with the param tagthese lines must appear between the starting and ending applet tags. The applet can read these values and use them to customize itself. Any number of param tags can appear between the starting and ending applet tags. Each parameter has a name and a value. Applet method getParameter retrieves the value associated with a specific parameter name and returns it as a string. The argument passed to getParameter is a string containing the name of the parameter in the param element. In this example, parameters represent the title and location of each Web site the user can select. Parameters specified for this applet are named title#, where the value of # starts at 0 and increments by 1 for each new title. Each title should have a corresponding location parameter of the form location#, where the value of # starts at 0 and increments
by 1 for each new location. The statement
String title = getParameter( "title0" );
gets the value associated with parameter "title0" and assigns it to reference title. If there is no param tag containing the specified parameter, getParameter returns null.
The applet (Fig. 24.2) obtains from the HTML document (Fig. 24.1) the choices that will be displayed in the applet's JList. Class SiteSelector uses a HashMap (package java.util) to store the Web site names and URLs. In this example, the key is the string in the JList that represents the Web site name, and the value is a URL object that stores the location of the Web site to display in the browser.
[Page 1110]
Class SiteSelector also contains an ArrayList (package java.util) in which the site names are placed so that they can be used to initialize the JList (one version of the JList constructor receives an array of Objects which is returned by ArrayList's toArray method). An ArrayList is a dynamically resizable array of references. Class ArrayList provides method add to add a new element to the end of the ArrayList.
(We provide discussions of classes ArrayList and HashMap in Chapter 19.)
Lines 2526 in the applet's init method (lines 2357) create a HashMap object and an ArrayList object. Line 29 calls our utility method getSitesFromHTMLParameters (declared at lines 6089) to obtain the HTML parameters from the HTML document that invoked the applet.
[Page 1112]
In method getSitesFromHTMLParameters, line 67 uses Applet method getParameter to obtain a Web site title. If the title is not null, the loop at lines 7088 begins executing. Line 73 uses Applet method getParameter to obtain the Web site location. Line 77 uses the location as the value of a new URL object. The URL constructor determines whether its argument represents a valid URL. If not, the URL constructor throws a MalformedURLException. Note that the URL constructor must be called in a TRy block. If the URL constructor generates a MalformedURLException, the call to printStackTrace (line 83) causes the program to output a stack trace to the Java console. On Windows machines, the Java console can be viewed by right clicking the Java icon in the notification area of the taskbar. Then the program attempts to obtain the next Web site title. The program does not add the site for the invalid URL to the HashMap, so the title will not be displayed in the JList.
[Page 1113]
For a proper URL, line 78 places the title and URL into the HashMap, and line 79 adds the title to the ArrayList. Line 87 gets the next title from the HTML document. When the call to getParameter at line 87 returns null, the loop terminates.
When method getSitesFromHTMLParameters returns to init, lines 3256 construct the applet's GUI. Line
32 adds the JLabel "Choose a site to browse" to the NORTH of the JFrame's BorderLayout. Line 34 creates JList siteChooser to allow the user to select a Webpage to view. Lines 3554 register a
ListSelectionListener to handle the siteChooser's events. Line 56 adds siteChooser to the CENTER of the JFrame's BorderLayout.
When the user selects one of the Web sites listed in siteChooser, the program calls method valueChanged (lines 3952). Line 42 obtains the selected site name from the JList. Line 45 passes the selected site name (the key) to HashMap method get, which locates and returns a reference to the corresponding URL object (the value) that is assigned to reference newDocument.
Line 48 uses Applet method getAppletContext to get a reference to an AppletContext object that represents the applet container. Line 51 uses the AppletContext reference browser to invoke method showDocument, which receives a URL object as an argument and passes it to the AppletContext (i.e., the browser). The browser displays in the current browser window the World Wide Web resource associated with that URL. In this example, all the resources are HTML documents.
For programmers familiar with HTML frames, there is a second version of AppletContext method showDocument that enables an applet to specify the so-called target frame in which to display the Web resource. This second version takes two argumentsa URL object specifying the resource to display and a string representing the target frame. There are some special target frames that can be used as the second argument. The target frame _blank results in a new Web browser window to display the content from the specified URL. The target frame _self specifies that the content from the specified URL should be displayed in the same frame as the applet (the applet's HTML page is replaced in this case). The target
frame _top specifies that the browser should remove the current frames in the browser window, then display the content from the specified URL in the current window. [Note: If you are interested in learning more about HTML, the CD that accompanies this book contains three chapters from our book Internet and World Wide Web How to Program, Third Edition that introduce the current version of HTML (known as XHTML) and the Web page formatting capability known as Cascading Style Sheets (CSS).]
Error-Prevention Tip 24.1
The applet in Fig. 24.2 must be run from a Web browser, such as Mozilla or Microsoft Internet Explorer, to see the results of displaying another Web page. The appletviewer is capable only of executing appletsit ignores all other HTML tags. If the Web sites in the program contained Java applets, only those applets would appear in the appletviewer when the user selected a Web site. Each applet would execute in a separate appletviewer window.
[Page 1114]
24.3. Reading a File on a Web Server
Our next example once again hides the networking details from us. The application in Fig. 24.3 uses Swing GUI component JEditorPane (from package javax.swing) to display the contents of a file on a Web server. The user inputs a URL in the JTextField at the top of the window, and the application displays the corresponding document (if it exists) in the JEditorPane. Class JEditorPane is able to render both plain text and HTML-formatted text, as illustrated in the two screen captures (Fig. 24.4), so this application acts as a simple Web browser. The application also demonstrates how to process
HyperlinkEvents when the user clicks a hyperlink in the HTML document. The techniques shown in this example can also be used in applets. However, an applet is allowed to read files only on the server from which it was downloaded.
Figure 24.3. Reading a file by opening a connection through a URL.
(This item is displayed on pages 1114 - 1115 in the print version)
1 // Fig. 24.3: ReadServerFile.java
2 // Use a JEditorPane to display the contents of a file on a Web server.
3import java.awt.BorderLayout;
4import java.awt.event.ActionEvent;
5import java.awt.event.ActionListener;
6import java.io.IOException;
7import javax.swing.JEditorPane;
8import javax.swing.JFrame;
9import javax.swing.JOptionPane;
10import javax.swing.JScrollPane;
11import javax.swing.JTextField;
12import javax.swing.event.HyperlinkEvent;
13import javax.swing.event.HyperlinkListener;
15public class ReadServerFile extends JFrame
16{
17private JTextField enterField; // JTextField to enter site name
18private JEditorPane contentsArea; // to display Web site
20// set up GUI
21public ReadServerFile()
22{
23super( "Simple Web Browser" );
25// create enterField and register its listener
26enterField = new JTextField( "Enter file URL here" );
27enterField.addActionListener(
28new ActionListener()
29{
30 |
// get |
document |
specified by |
user |
31 |
public |
void actionPerformed( |
ActionEvent event ) |
|
32 |
{ |
|
|
|
33 |
getThePage( event.getActionCommand() ); |
|||
34 |
} // end method |
actionPerformed |
||
35} // end inner class
36); // end call to addActionListener
38add( enterField, BorderLayout.NORTH );
40contentsArea = new JEditorPane(); // create contentsArea
41contentsArea.setEditable( false );
42contentsArea.addHyperlinkListener(
43new HyperlinkListener()
44{
45 |
// if user clicked hyperlink, go to specified page |
|
46 |
public void hyperlinkUpdate( |
HyperlinkEvent event ) |
47 |
{ |
|
48 |
if ( event.getEventType() |
== |
49 |
HyperlinkEvent.EventType.ACTIVATED ) |
50 |
getThePage( event.getURL().toString() ); |
51 |
} // end method hyperlinkUpdate |
52} // end inner class
53); // end call to addHyperlinkListener
55add( new JScrollPane( contentsArea ), BorderLayout.CENTER );
56setSize( 400, 300 ); // set size of window
57setVisible( true ); // show window
58} // end ReadServerFile constructor
60// load document
61private void getThePage( String location )
62{
63try // load document and display location
64{
65contentsArea.setPage( location ); // set the page
66enterField.setText( location ); // set the text
67} // end try
68catch ( IOException ioException )
69{
70JOptionPane.showMessageDialog( this,
71 |
"Error retrieving |
specified URL", "Bad URL", |
72 |
JOptionPane.ERROR |
_MESSAGE ); |
73} // end catch
74} // end method getThePage
75} // end class ReadServerFile
Figure 24.4. Test class for ReadServerFile.
(This item is displayed on pages 1115 - 1116 in the print version)
1 // Fig. 24.4: ReadServerFileTest.java 2 // Create and start a ReadServerFile. 3 import javax.swing.JFrame;
4
5public class ReadServerFileTest
6{
7public static void main( String args[] )
8{
9ReadServerFile application = new ReadServerFile();
10application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
11} // end main
12} // end class ReadServerFileTest
[View full size image]
[Page 1116]
The application class ReadServerFile contains JTextField enterField, in which the user enters the URL of the file to read and JEditorPane contentsArea to display the contents of the file. When the user presses the Enter key in enterField, the application calls method actionPerformed (lines 3134). Line 33 uses ActionEvent method getActionCommand to get the string the user input in the JTextField and passes the string to utility method getThePage (lines 6174).
Line 65 invokes JEditorPane method setPage to download the document specified by location and display it in the JEditorPane. If there is an error downloading the document, method setPage throws an IOException. Also, if an invalid URL is specified, a MalformedURLException (a subclass of IOException) occurs. If the document loads successfully, line 66 displays the current location in enterField.
Typically, an HTML document contains hyperlinkstext, images or GUI components which, when clicked, provide quick access to another document on the Web. If a JEditorPane contains an HTML document and the user clicks a hyperlink, the JEditorPane generates a HyperlinkEvent (package javax.swing.event) and notifies all registered HyperlinkListeners (package javax.swing.event) of that event. Lines 4253 register a HyperlinkListener to handle HyperlinkEvents. When a HyperlinkEvent occurs, the program calls method hyperlinkUpdate (lines
4651). Lines 4849 use HyperlinkEvent method getEventType to determine the type of the
HyperlinkEvent. Class HyperlinkEvent contains a public nested class called EventType that declares three static EventType objects, which represent the hyperlink event types. ACTIVATED indicates that the user clicked a hyperlink to change Web pages, ENTERED indicates that the user moved the mouse over a hyperlink and EXITED indicates that the user moved the mouse away from a hyperlink. If a hyperlink was ACTIVATED, line 50 uses HyperlinkEvent method getURL to obtain the URL represented by the hyperlink. Method toString converts the returned URL to a string that can be passed to utility method getThePage.
[Page 1117]
Look-and-Feel Observation 24.1
A JEditorPane generates HyperlinkEvents only if it is uneditable.
[Page 1117 (continued)]
24.4. Establishing a Simple Server Using Stream Sockets
The two examples discussed so far use high-level Java networking capabilities to communicate between applications. In the examples, it was not the Java programmer's responsibility to establish the connection between a client and a server. The first program relied on the Web browser to communicate with a Web server. The second program relied on a JEditorPane to perform the connection. This section begins our discussion of creating your own applications that can communicate with one another.
Establishing a simple server in Java requires five steps. Step 1 is to create a ServerSocket object. A call to the ServerSocket constructor, such as
ServerSocket server = new ServerSocket( portNumber, queueLength );
registers an available TCP port number and specifies a maximum number of clients that can wait to connect to the server (i.e., the queue length). The port number is used by clients to locate the server application on the server computer. This is often called the handshake point. If the queue is full, the server refuses client connections. The constructor establishes the port where the server waits for connections from clientsa process known as binding the server to the port. Each client will ask to connect to the server on this port. Only one application at a time can be bound to a specific port on the server.
Software Engineering Observation 24.1
Port numbers can be between 0 and 65,535. Most operating systems reserve port numbers below 1024 for system services (e.g., e-mail and World Wide Web servers). Generally, these ports should not be specified as connection ports in user programs. In fact, some operating systems require special access privileges to bind to port numbers below 1024.
Programs manage each client connection with a Socket object. In Step 2, the server listens indefinitely (or blocks) for an attempt by a client to connect. To listen for a client connection, the program calls ServerSocket method accept, as in
Socket connection = server.accept();
[Page 1118]
which returns a Socket when a connection with a client is established. The Socket allows the server to interact with the client. The interactions with the client actually occur at a different server port from the handshake point. This allows the port specified in Step 1 to be used again in a multithreaded server to accept another client connection. We demonstrate this concept in Section 24.8.
Step 3 is to get the OutputStream and InputStream objects that enable the server to communicate with the client by sending and receiving bytes. The server sends information to the client via an OutputStream and receives information from the client via an InputStream. The server invokes method getOutputStream on the Socket to get a reference to the Socket's OutputStream and invokes method getInputStream on the Socket to get a reference to the Socket's InputStream.
The stream objects can be used to send or receive individual bytes or sequences of bytes with the OutputStream's method write and the InputStream's method read, respectively. Often it is useful to send or receive values of primitive types (e.g., int and double) or Serializable objects (e.g., Strings or other serializable types) rather than sending bytes. In this case, we can use the techniques discussed in Chapter 14 to wrap other stream types (e.g., ObjectOutputStream and ObjectInputStream) around
