import java.awt.*; // For BorderLayout, GridLayout, Font, Color. import java.awt.event.*; import java.util.*; import javax.swing.*; /** A graphical client that lets you interactively connect to * Web servers and send custom request lines and * request headers. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * . * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class WebClient extends JPanel implements Runnable, Interruptible, ActionListener { public static void main(String[] args) { WindowUtilities.setNativeLookAndFeel(); WindowUtilities.openInJFrame(new WebClient(), 600, 700, "Web Client", SystemColor.control); } private LabeledTextField hostField, portField, requestLineField; private JTextArea requestHeadersArea, resultArea; private String host, requestLine; private int port; private String[] requestHeaders = new String[30]; private JButton submitButton, interruptButton; private boolean isInterrupted = false; public WebClient() { setLayout(new BorderLayout(5, 30)); int fontSize = 14; Font labelFont = new Font("Serif", Font.BOLD, fontSize); Font headingFont = new Font("SansSerif", Font.BOLD, fontSize+4); Font textFont = new Font("Monospaced", Font.BOLD, fontSize-2); JPanel inputPanel = new JPanel(); inputPanel.setLayout(new BorderLayout()); JPanel labelPanel = new JPanel(); labelPanel.setLayout(new GridLayout(4,1)); hostField = new LabeledTextField("Host:", labelFont, 30, textFont); portField = new LabeledTextField("Port:", labelFont, "80", 5, textFont); // Use HTTP 1.0 for compatibility with the most servers. // If you switch this to 1.1, you *must* supply a // Host: request header. requestLineField = new LabeledTextField("Request Line:", labelFont, "GET / HTTP/1.0", 50, textFont); labelPanel.add(hostField); labelPanel.add(portField); labelPanel.add(requestLineField); JLabel requestHeadersLabel = new JLabel("Request Headers:"); requestHeadersLabel.setFont(labelFont); labelPanel.add(requestHeadersLabel); inputPanel.add(labelPanel, BorderLayout.NORTH); requestHeadersArea = new JTextArea(5, 80); requestHeadersArea.setFont(textFont); JScrollPane headerScrollArea = new JScrollPane(requestHeadersArea); inputPanel.add(headerScrollArea, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); submitButton = new JButton("Submit Request"); submitButton.addActionListener(this); submitButton.setFont(labelFont); buttonPanel.add(submitButton); inputPanel.add(buttonPanel, BorderLayout.SOUTH); add(inputPanel, BorderLayout.NORTH); JPanel resultPanel = new JPanel(); resultPanel.setLayout(new BorderLayout()); JLabel resultLabel = new JLabel("Results", JLabel.CENTER); resultLabel.setFont(headingFont); resultPanel.add(resultLabel, BorderLayout.NORTH); resultArea = new JTextArea(); resultArea.setFont(textFont); JScrollPane resultScrollArea = new JScrollPane(resultArea); resultPanel.add(resultScrollArea, BorderLayout.CENTER); JPanel interruptPanel = new JPanel(); interruptButton = new JButton("Interrupt Download"); interruptButton.addActionListener(this); interruptButton.setFont(labelFont); interruptPanel.add(interruptButton); resultPanel.add(interruptPanel, BorderLayout.SOUTH); add(resultPanel, BorderLayout.CENTER); } public void actionPerformed(ActionEvent event) { if (event.getSource() == submitButton) { Thread downloader = new Thread(this); downloader.start(); } else if (event.getSource() == interruptButton) { isInterrupted = true; } } public void run() { isInterrupted = false; if (hasLegalArgs()) new HttpClient(host, port, requestLine, requestHeaders, resultArea, this); } public boolean isInterrupted() { return(isInterrupted); } private boolean hasLegalArgs() { host = hostField.getTextField().getText(); if (host.length() == 0) { report("Missing hostname"); return(false); } String portString = portField.getTextField().getText(); if (portString.length() == 0) { report("Missing port number"); return(false); } try { port = Integer.parseInt(portString); } catch(NumberFormatException nfe) { report("Illegal port number: " + portString); return(false); } requestLine = requestLineField.getTextField().getText(); if (requestLine.length() == 0) { report("Missing request line"); return(false); } getRequestHeaders(); return(true); } private void report(String s) { resultArea.setText(s); } private void getRequestHeaders() { for(int i=0; i * LabeledTextField ltf = new LabeledTextField(...); * ltf.getLabel().someLabelMethod(...); *
*/ public JLabel getLabel() { return(label); } /** The TextField at the right side of the * LabeledTextField. */ public JTextField getTextField() { return(textField); } } Interruptible.java Polls to see if the user choose to interrupt the current network download. /** An interface for classes that can be polled to see * if they've been interrupted. Used by HttpClient * and WebClient to allow the user to interrupt a network * download. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * . * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public interface Interruptible { public boolean isInterrupted(); } NetworkClient.java Starting point for a network client to communicate with a remote computer. import java.net.*; import java.io.*; /** A starting point for network clients. You'll need to * override handleConnection, but in many cases connect can * remain unchanged. It uses SocketUtil to simplify the * creation of the PrintWriter and BufferedReader. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class NetworkClient { protected String host; protected int port; /** Register host and port. The connection won't * actually be established until you call * connect. */ public NetworkClient(String host, int port) { this.host = host; this.port = port; } /** Establishes the connection, then passes the socket * to handleConnection. */ public void connect() { try { Socket client = new Socket(host, port); handleConnection(client); } catch(UnknownHostException uhe) { System.out.println("Unknown host: " + host); uhe.printStackTrace(); } catch(IOException ioe) { System.out.println("IOException: " + ioe); ioe.printStackTrace(); } } /** This is the method you will override when * making a network client for your task. * The default version sends a single line * ("Generic Network Client") to the server, * reads one line of response, prints it, then exits. */ protected void handleConnection(Socket client) throws IOException { PrintWriter out = SocketUtil.getWriter(client); BufferedReader in = SocketUtil.getReader(client); out.println("Generic Network Client"); System.out.println ("Generic Network Client:\n" + "Made connection to " + host + " and got '" + in.readLine() + "' in response"); client.close(); } /** The hostname of the server we're contacting. */ public String getHost() { return(host); } /** The port connection will be made on. */ public int getPort() { return(port); } } SocketUtil.java: Provides utilities for wrapping a BufferedReader and PrintWriter around the Socket's input and output streams, respectively. import java.net.*; import java.io.*; /** A shorthand way to create BufferedReaders and * PrintWriters associated with a Socket. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * . * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class SocketUtil { /** Make a BufferedReader to get incoming data. */ public static BufferedReader getReader(Socket s) throws IOException { return(new BufferedReader( new InputStreamReader(s.getInputStream()))); } /** Make a PrintWriter to send outgoing data. * This PrintWriter will automatically flush stream * when println is called. */ public static PrintWriter getWriter(Socket s) throws IOException { // Second argument of true means autoflush. return(new PrintWriter(s.getOutputStream(), true)); } } WindowUtilities.java Simplifies the setting of native look and feel. import javax.swing.*; import java.awt.*; // For Color and Container classes. /** A few utilities that simplify using windows in Swing. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class WindowUtilities { /** Tell system to use native look and feel, as in previous * releases. Metal (Java) LAF is the default otherwise. */ public static void setNativeLookAndFeel() { try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch(Exception e) { System.out.println("Error setting native LAF: " + e); } } public static void setJavaLookAndFeel() { try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName()); } catch(Exception e) { System.out.println("Error setting Java LAF: " + e); } } public static void setMotifLookAndFeel() { try { UIManager.setLookAndFeel( "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); } catch(Exception e) { System.out.println("Error setting Motif LAF: " + e); } } /** A simplified way to see a JPanel or other Container. Pops * up a JFrame with specified Container as the content pane. */ public static JFrame openInJFrame(Container content, int width, int height, String title, Color bgColor) { JFrame frame = new JFrame(title); frame.setBackground(bgColor); content.setBackground(bgColor); frame.setSize(width, height); frame.setContentPane(content); frame.addWindowListener(new ExitListener()); frame.setVisible(true); return(frame); } /** Uses Color.white as the background color. */ public static JFrame openInJFrame(Container content, int width, int height, String title) { return(openInJFrame(content, width, height, title, Color.white)); } /** Uses Color.white as the background color, and the * name of the Container's class as the JFrame title. */ public static JFrame openInJFrame(Container content, int width, int height) { return(openInJFrame(content, width, height, content.getClass().getName(), Color.white)); } } ExitListener.java WindowListener for applications in this chapter. import java.awt.*; import java.awt.event.*; /** A listener that you attach to the top-level JFrame of * your application, so that quitting the frame exits the * application. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class ExitListener extends WindowAdapter { public void windowClosing(WindowEvent event) { System.exit(0); } }