import java.awt.*;
import java.awt.event.*;
/** A Frame that you can actually quit. Used as the starting
* point for most Java 1.1 graphical applications.
*
public class CloseableFrame extends Frame {
public CloseableFrame(String title) {
super(title);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
}
/** Since we are doing something permanent, we need
* to call super.processWindowEvent first.
*/
public void processWindowEvent(WindowEvent event) {
super.processWindowEvent(event); // Handle listeners.
if (event.getID() == WindowEvent.WINDOW_CLOSING) {
// If the frame is used in an applet, use dispose().
System.exit(0);
}
}
}
Aug 26
A Frame that can actually quit
Aug 26
creating a simple Swing application using a JFrame
JFrameExample.java Demonstrates creating a simple Swing application using a JFrame. As with a JApplet, components must be added to the content pane, instead of the window directly.import java.awt.*;
import javax.swing.*;
/** Tiny example showing the main difference in using
* JFrame instead of Frame: using the content pane
* and getting the Java (Metal) look and feel by default
* instead of the native look and feel.
*
*/
public class JFrameExample {
public static void main(String[] args) {
WindowUtilities.setNativeLookAndFeel();
JFrame f = new JFrame("This is a test");
f.setSize(400, 150);
Container content = f.getContentPane();
content.setBackground(Color.white);
content.setLayout(new FlowLayout());
content.add(new JButton("Button 1"));
content.add(new JButton("Button 2"));
content.add(new JButton("Button 3"));
f.addWindowListener(new ExitListener());
f.setVisible(true);
}
}
Aug 26
Explicit placement of five buttons with the layout manager turned off
NullTest.java Explicit placement of five buttons with the layout manager turned off (set to null)
##########################
import java.applet.Applet;
import java.awt.*;
/** Layout managers are intended to help you, but there
* is no law saying you have to use them.
* Set the layout to null to turn them off.
*
*******************
public class NullTest extends Applet {
public void init() {
setLayout(null);
Button b1 = new Button("Button 1");
Button b2 = new Button("Button 2");
Button b3 = new Button("Button 3");
Button b4 = new Button("Button 4");
Button b5 = new Button("Button 5");
b1.setBounds(0, 0, 150, 50);
b2.setBounds(150, 0, 75, 50);
b3.setBounds(225, 0, 75, 50);
b4.setBounds(25, 60, 100, 40);
b5.setBounds(175, 60, 100, 40);
add(b1);
add(b2);
add(b3);
add(b4);
add(b5);
}
}
Aug 26
JTree Examples
SimpleTree.java Basic tree built out of DefaultMutableTreeNodes. A DefualtMutableTreeNode is a starting point for a root node, in which children nodes can be added.
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
/** Example tree built out of DefaultMutableTreeNodes.
*
*/
public class SimpleTree extends JFrame {
public static void main(String[] args) {
new SimpleTree();
}
public SimpleTree() {
super("Creating a Simple JTree");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
Object[] hierarchy =
{ "javax.swing",
"javax.swing.border",
"javax.swing.colorchooser",
"javax.swing.event",
"javax.swing.filechooser",
new Object[] { "javax.swing.plaf",
"javax.swing.plaf.basic",
"javax.swing.plaf.metal",
"javax.swing.plaf.multi" },
"javax.swing.table",
new Object[] { "javax.swing.text",
new Object[] { "javax.swing.text.html",
"javax.swing.text.html.parser" },
"javax.swing.text.rtf" },
"javax.swing.tree",
"javax.swing.undo" };
DefaultMutableTreeNode root = processHierarchy(hierarchy);
JTree tree = new JTree(root);
content.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize(275, 300);
setVisible(true);
}
/** Small routine that will make a node out of the first entry
* in the array, then make nodes out of subsequent entries
* and make them child nodes of the first one. The process
* is repeated recursively for entries that are arrays.
*/
private DefaultMutableTreeNode processHierarchy(
Object[] hierarchy) {
DefaultMutableTreeNode node =
new DefaultMutableTreeNode(hierarchy[0]);
DefaultMutableTreeNode child;
for(int i=1; i 0) {
try {
n = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {
System.out.println(
"Can't parse number; using default of " + n);
}
}
new DynamicTree(n);
}
public DynamicTree(int n) {
super("Creating a Dynamic JTree");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
JTree tree = new JTree(new OutlineNode(1, n));
content.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize(300, 475);
setVisible(true);
}
}
* OutlineNode.java A simple tree node that builds its children.
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
/** Simple TreeNode that builds children on the fly.
* The key idea is that getChildCount is always called before
* any actual children are requested. That way, getChildCount
* builds the children if they don't already exist.
*
* In this case, it just builds an "outline" tree. I.e.,
* if the root is current node is "x", the children are
* "x.0", "x.1", "x.2", and "x.3".
*
*
*/
public class OutlineNode extends DefaultMutableTreeNode {
private boolean areChildrenDefined = false;
private int outlineNum;
private int numChildren;
public OutlineNode(int outlineNum, int numChildren) {
this.outlineNum = outlineNum;
this.numChildren = numChildren;
}
public boolean isLeaf() {
return(false);
}
public int getChildCount() {
if (!areChildrenDefined) {
defineChildNodes();
}
return(super.getChildCount());
}
private void defineChildNodes() {
// You must set the flag before defining children if you
// use "add" for the new children. Otherwise, you get an
// infinite recursive loop since add results in a call
// to getChildCount. However, you could use "insert" in such
// a case.
areChildrenDefined = true;
for(int i=0; i
Aug 26
Printing in Java 2
*
o PrintExample.java Demonstrates printing a Graphics2D object.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.print.*;
/** An example of a printable window in Java 1.2. The key point
* here is that any component is printable in Java 1.2.
* However, you have to be careful to turn off double buffering
* globally (not just for the top-level window).
* See the PrintUtilities class for the printComponent method
* that lets you print an arbitrary component with a single
* function call.
*
*/
public class PrintExample extends JFrame
implements ActionListener {
public static void main(String[] args) {
new PrintExample();
}
public PrintExample() {
super("Printing Swing Components in JDK 1.2");
WindowUtilities.setNativeLookAndFeel();
addWindowListener(new ExitListener());
Container content = getContentPane();
JButton printButton = new JButton("Print");
printButton.addActionListener(this);
JPanel buttonPanel = new JPanel();
buttonPanel.setBackground(Color.white);
buttonPanel.add(printButton);
content.add(buttonPanel, BorderLayout.SOUTH);
DrawingPanel drawingPanel = new DrawingPanel();
content.add(drawingPanel, BorderLayout.CENTER);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
PrintUtilities.printComponent(this);
}
}
Uses the following classes:
+ PrintUtilities.java Simple utility class to support printing graphical windows in JDK 1.2.
import java.awt.*;
import javax.swing.*;
import java.awt.print.*;
/** A simple utility class that lets you very simply print
* an arbitrary component in JDK 1.2. Just pass the
* component to PrintUtilities.printComponent. The
* component you want to print doesn't need a print method
* and doesn't have to implement any interface or do
* anything special at all.
*
* If you are going to be printing many times, it is marginally
* more efficient to first do the following:
*
* PrintUtilities printHelper =
* new PrintUtilities(theComponent);
*
* then later do printHelper.print(). But this is a very tiny
* difference, so in most cases just do the simpler
* PrintUtilities.printComponent(componentToBePrinted).
*
*/
public class PrintUtilities implements Printable {
protected Component componentToBePrinted;
public static void printComponent(Component c) {
new PrintUtilities(c).print();
}
public PrintUtilities(Component componentToBePrinted) {
this.componentToBePrinted = componentToBePrinted;
}
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(this);
if (printJob.printDialog())
try {
printJob.print();
} catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
// General print routine for JDK 1.2. Use PrintUtilities2
// for printing in JDK 1.3.
public int print(Graphics g, PageFormat pageFormat,
int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
/** The speed and quality of printing suffers dramatically if
* any of the containers have double buffering turned on,
* so this turns it off globally. This step is only
* required in JDK 1.2.
*/
public static void disableDoubleBuffering(Component c) {
RepaintManager currentManager =
RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(false);
}
/** Reenables double buffering globally. This step is only
* required in JDK 1.2.
*/
public static void enableDoubleBuffering(Component c) {
RepaintManager currentManager =
RepaintManager.currentManager(c);
currentManager.setDoubleBufferingEnabled(true);
}
}
//
+ DrawingPanel.java A basic JPanel containing a Java 2D drawing.
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
/** A window with a custom paintComponent method.
* Illustrates that you can make a general-purpose method
* that can print any component, regardless of whether
* that component performs custom drawing.
* See the PrintUtilities class for the printComponent method
* that lets you print an arbitrary component with a single
* function call.
*
*/
public class DrawingPanel extends JPanel {
private int fontSize = 90;
private String message = "Java 2D";
private int messageWidth;
public DrawingPanel() {
setBackground(Color.white);
Font font = new Font("Serif", Font.PLAIN, fontSize);
setFont(font);
FontMetrics metrics = getFontMetrics(font);
messageWidth = metrics.stringWidth(message);
int width = messageWidth*5/3;
int height = fontSize*3;
setPreferredSize(new Dimension(width, height));
}
/** Draws a black string with a tall angled "shadow"
* of the string behind it.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
int x = messageWidth/10;
int y = fontSize*5/2;
g2d.translate(x, y);
g2d.setPaint(Color.lightGray);
AffineTransform origTransform = g2d.getTransform();
g2d.shear(-0.95, 0);
g2d.scale(1, 3);
g2d.drawString(message, 0, 0);
g2d.setTransform(origTransform);
g2d.setPaint(Color.black);
g2d.drawString(message, 0, 0);
}
}
o PrintUtilities2.java Simple utility class to support printing graphical windows in JDK 1.3 and later. Inherits from PrintUtilities.java.
import java.awt.*;
import javax.swing.*;
import java.awt.print.*;
/** A simple utility class for printing an arbitrary
* component in JDK 1.3. The class relies on the
* fact that in JDK 1.3 the JComponent class overrides
* print (in Container) to automatically set a flag
* that disables double buffering before the component
* is painted. If the printing flag is set, paint calls
* printComponent, printBorder, and printChildren.
*
* To print a component, just pass the component to
* PrintUtilities2.printComponent(componentToBePrinted).
*
*/
public class PrintUtilities2 extends PrintUtilities {
public static void printComponent(Component c) {
new PrintUtilities2(c).print();
}
public PrintUtilities2(Component componentToBePrinted) {
super(componentToBePrinted);
}
// General print routine for JDK 1.3. Use PrintUtilities1
// for printing in JDK 1.2.
public int print(Graphics g, PageFormat pageFormat,
int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),
pageFormat.getImageableY());
componentToBePrinted.print(g2d);
return(PAGE_EXISTS);
}
}
}
* FileTransfer.java Demonstrates the proper technique for updating Swing components in a multithreaded program.
/**
// Final version of FileTransfer. Modification of the
// label is thread safe.
public class FileTransfer extends Thread {
private String filename;
private JLabel label;
public FileTransfer(String filename, JLabel label) {
this.filename = filename;
this.label = label;
}
public void run() {
try {
// Place the runnable object to update the label
// on the event queue. The invokeAndWait method
// will block until the label is updated.
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
label.setText("Transferring " + filename);
}
});
} catch(InvocationTargetException ite) {
} catch(InterruptedException ie) { }
// Transfer file to server. Lengthy process.
doTransfer(...);
// Perform the final update to the label from
// within the runnable object. Use invokeLater;
// blocking is not necessary.
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
label.setText("Transfer completed");
}
});
}
}
* WindowUtilities.java Utility class that simplifies creating a window and setting the look and feel.
* ExitListener.java A WindowListener with support to close the window.
Aug 26
BetterCircleTest.java
**********************
BetterCircleTest.java
**********************
import java.awt.*;
import java.applet.Applet;
/** Position circles down the diagonal so that their borders
* just touch. Illustrates that Java 1.1 lightweight
* components can be partially transparent.
*
*/
public class BetterCircleTest extends Applet {
public void init() {
setBackground(Color.lightGray);
setLayout(null);
BetterCircle circle;
int radius = getSize().width/6;
int deltaX = round(2.0 * (double)radius / Math.sqrt(2.0));
for (int x=radius; x<6*radius; x=x+deltaX) {
circle = new BetterCircle(Color.black, radius);
add(circle);
circle.setCenter(x, x);
}
}
private int round(double num) {
return((int)Math.round(num));
}
}
********************************
BetterCircle.java
********************************
import java.awt.*;
/** An improved variation of the Circle class that uses Java 1.1
* lightweight components instead of Canvas.
*
*/
public class BetterCircle extends Component {
private Dimension preferredDimension;
private int width, height;
public BetterCircle(Color foreground, int radius) {
setForeground(foreground);
width = 2*radius;
height = 2*radius;
preferredDimension = new Dimension(width, height);
setSize(preferredDimension);
}
public void paint(Graphics g) {
g.setColor(getForeground());
g.fillOval(0, 0, width, height);
}
public void setCenter(int x, int y) {
setLocation(x - width/2, y - height/2);
}
/** Report the original size as the preferred size.
* That way, the BetterCircle doesn't get
* shrunk by layout managers.
*/
public Dimension getPreferredSize() {
return(preferredDimension);
}
/** Report same thing for minimum size as
* preferred size.
*/
public Dimension getMinimumSize() {
return(preferredDimension);
}
}
*******************************
Aug 25
RMI Example – Numerical Integration, a more realistic RMI example that sends an evaluatable object (function) from a client to a server for numerical integration.
Integral.java Performs actual numerical integration of the function (evaluatable object).
/** A class to calculate summations and numeric integrals. The
* integral is calculated according to the midpoint rule.
*
* 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 Integral {
/** Returns the sum of f(x) from x=start to x=stop, where the
* function f is defined by the evaluate method of the
* Evaluatable object.
*/
public static double sum(double start, double stop,
double stepSize,
Evaluatable evalObj) {
double sum = 0.0, current = start;
while (current <= stop) {
sum += evalObj.evaluate(current);
current += stepSize;
}
return(sum);
}
/** Returns an approximation of the integral of f(x) from
* start to stop, using the midpoint rule. The function f is
* defined by the evaluate method of the Evaluatable object.
*/
public static double integrate(double start, double stop,
int numSteps,
Evaluatable evalObj) {
double stepSize = (stop - start) / (double)numSteps;
start = start + stepSize / 2.0;
return(stepSize * sum(start, stop, stepSize, evalObj));
}
}
Evaluatable.java An interface for evaluating functions. Requires the Evaluatable object to implement the evaluate method.
/** An interface for evaluating functions y = f(x) at a specific
* value. Both x and y are double-precision floating-point
* numbers.
*
* 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 Evaluatable {
public double evaluate(double value);
}
RemoteIntegral.java Establishes the methods in the remote object available to the client.
import java.rmi.*;
/** Interface for remote numeric integration object.
*
* 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 RemoteIntegral extends Remote {
public double sum(double start, double stop, double stepSize,
Evaluatable evalObj)
throws RemoteException;
public double integrate(double start, double stop,
int numSteps, Evaluatable evalObj)
throws RemoteException;
}
RemoteIntegralClient.java The client that sends an Evaluatable object to the remote server for integration.
import java.rmi.*;
import java.net.*;
import java.io.*;
/** This class calculates a variety of numerical integration
* values, printing the results of successively more accurate
* approximations. The actual computation is performed on a
* remote machine whose hostname is specified as a command-
* line argument.
*
* 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 RemoteIntegralClient {
public static void main(String[] args) {
try {
String host = (args.length > 0) ? args[0] : "localhost";
RemoteIntegral remoteIntegral =
(RemoteIntegral)Naming.lookup("rmi://" + host +
"/RemoteIntegral");
for(int steps=10; steps<=10000; steps*=10) {
System.out.println
("Approximated with " + steps + " steps:" +
"\n Integral from 0 to pi of sin(x)=" +
remoteIntegral.integrate(0.0, Math.PI,
steps, new Sin()) +
"\n Integral from pi/2 to pi of cos(x)=" +
remoteIntegral.integrate(Math.PI/2.0, Math.PI,
steps, new Cos()) +
"\n Integral from 0 to 5 of x^2=" +
remoteIntegral.integrate(0.0, 5.0, steps,
new Quadratic()));
}
System.out.println
("`Correct' answer using Math library:" +
"\n Integral from 0 to pi of sin(x)=" +
(-Math.cos(Math.PI) - -Math.cos(0.0)) +
"\n Integral from pi/2 to pi of cos(x)=" +
(Math.sin(Math.PI) - Math.sin(Math.PI/2.0)) +
"\n Integral from 0 to 5 of x^2=" +
(Math.pow(5.0, 3.0) / 3.0));
} catch(RemoteException re) {
System.out.println("RemoteException: " + re);
} catch(NotBoundException nbe) {
System.out.println("NotBoundException: " + nbe);
} catch(MalformedURLException mfe) {
System.out.println("MalformedURLException: " + mfe);
}
}
}
Sin.java Evaluatable version of sin(x).
import java.io.Serializable;
/** An evaluatable version of sin(x).
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* .
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
class Sin implements Evaluatable, Serializable {
public double evaluate(double val) {
return(Math.sin(val));
}
public String toString() {
return("Sin");
}
}
Cos.java Evaluatable version of cos(x).
import java.io.Serializable;
/** An evaluatable version of cos(x).
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* .
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
class Cos implements Evaluatable, Serializable {
public double evaluate(double val) {
return(Math.cos(val));
}
public String toString() {
return("Cosine");
}
}
Quadratic.java Evaluatable version of x2.
import java.io.Serializable;
/** An evaluatable version of x^2.
*
* Taken from Core Web Programming from
* Prentice Hall and Sun Microsystems Press,
* .
* © 2001 Marty Hall and Larry Brown;
* may be freely used or adapted.
*/
class Quadratic implements Evaluatable, Serializable {
public double evaluate(double val) {
return(val * val);
}
public String toString() {
return("Quadratic");
}
}
RemoteIntegralImpl.java The remote object which provides a concrete implementation of the RemoteIntegral interface.
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
/** The actual implementation of the RemoteIntegral interface.
*
* 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 RemoteIntegralImpl extends UnicastRemoteObject
implements RemoteIntegral {
/** Constructor must throw RemoteException. */
public RemoteIntegralImpl() throws RemoteException {}
/** Returns the sum of f(x) from x=start to x=stop, where the
* function f is defined by the evaluate method of the
* Evaluatable object.
*/
public double sum(double start, double stop, double stepSize,
Evaluatable evalObj) {
return(Integral.sum(start, stop, stepSize, evalObj));
}
/** Returns an approximation of the integral of f(x) from
* start to stop, using the midpoint rule. The function f is
* defined by the evaluate method of the Evaluatable object.
* @see #sum
*/
public double integrate(double start, double stop, int numSteps,
Evaluatable evalObj) {
return(Integral.integrate(start, stop, numSteps, evalObj));
}
}
RemoteIntegralServer.java Creates an instance of RemoteIntegralImpl on the remote server and binds the object in the registry for lookup by the client.
import java.rmi.*;
import java.net.*;
/** Creates a RemoteIntegralImpl object and registers it under
* the name 'RemoteIntegral' so that remote clients can connect
* to it for numeric integration results. The idea is to place
* this server on a workstation with very fast floating-point
* capabilities, while slower interfaces can run on smaller
* computers but still use the integration routines.
*
* 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 RemoteIntegralServer {
public static void main(String[] args) {
try {
RemoteIntegralImpl integral = new RemoteIntegralImpl();
Naming.rebind("rmi:///RemoteIntegral", integral);
} catch(RemoteException re) {
System.out.println("RemoteException: " + re);
} catch(MalformedURLException mfe) {
System.out.println("MalformedURLException: " + mfe);
}
}
}
RemoteIntegralClient2.java An enterprise version of the client that imposes a security manager to support the Java 2 RMI 1.2 stub protocol.
import java.rmi.*;
import java.net.*;
import java.io.*;
/** This class is a Java 2 version of RemoteIntegralClient
* that imposes a SecurityManager to allow the client to
* connect to a remote machine for loading stub files and
* performing numerical integration through a remote
* object.
*
* 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 RemoteIntegralClient2 {
public static void main(String[] args) {
try {
System.setSecurityManager(new RMISecurityManager());
String host =
(args.length > 0) ? args[0] : "localhost";
RemoteIntegral remoteIntegral =
(RemoteIntegral)Naming.lookup("rmi://" + host +
"/RemoteIntegral");
for(int steps=10; steps<=10000; steps*=10) {
System.out.println
("Approximated with " + steps + " steps:" +
"\n Integral from 0 to pi of sin(x)=" +
remoteIntegral.integrate(0.0, Math.PI,
steps, new Sin()) +
"\n Integral from pi/2 to pi of cos(x)=" +
remoteIntegral.integrate(Math.PI/2.0, Math.PI,
steps, new Cos()) +
"\n Integral from 0 to 5 of x^2=" +
remoteIntegral.integrate(0.0, 5.0, steps,
new Quadratic()));
}
System.out.println
("`Correct' answer using Math library:" +
"\n Integral from 0 to pi of sin(x)=" +
(-Math.cos(Math.PI) - -Math.cos(0.0)) +
"\n Integral from pi/2 to pi of cos(x)=" +
(Math.sin(Math.PI) - Math.sin(Math.PI/2.0)) +
"\n Integral from 0 to 5 of x^2=" +
(Math.pow(5.0, 3.0) / 3.0));
} catch(RemoteException re) {
System.out.println("RemoteException: " + re);
} catch(NotBoundException nbe) {
System.out.println("NotBoundException: " + nbe);
} catch(MalformedURLException mfe) {
System.out.println("MalformedURLException: " + mfe);
}
}
}
rmiclient.policy Policy file for the client. Grants permissions for the client to connect to the RMI server and Web server.
// Taken from Core Web Programming from
// Prentice Hall and Sun Microsystems Press,
// .
// © 2001 Marty Hall and Larry Brown;
// may be freely used or adapted.
grant {
// rmihost - RMI registry and the server
// webhost - HTTP server for stub classes
permission java.net.SocketPermission
"rmihost:1024-65535", "connect";
permission java.net.SocketPermission
"webhost:80", "connect";
};
Aug 25
A JPanel that displays six radio buttons with labels.
A JPanel that displays six radio buttons with labels.
import java.awt.*;
import javax.swing.*;
/** A JPanel that displays six JRadioButtons.
*
*.
*/
public class SixChoicePanel extends JPanel {
public SixChoicePanel(String title, String[] buttonLabels) {
super(new GridLayout(3, 2));
setBackground(Color.lightGray);
setBorder(BorderFactory.createTitledBorder(title));
ButtonGroup group = new ButtonGroup();
JRadioButton option;
int halfLength = buttonLabels.length/2; // Assumes even length
for(int i=0; i
Aug 25
ThreadedEchoServer.java A multithreaded version of EchoServer, where each client request is serviced on a separate thread. Requires the following classes
import java.net.*;
import java.io.*;
/** A multithreaded variation of EchoServer.
*
* 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 ThreadedEchoServer extends EchoServer
implements Runnable {
public static void main(String[] args) {
int port = 8088;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {}
}
ThreadedEchoServer echoServer =
new ThreadedEchoServer(port, 0);
echoServer.serverName = "Threaded EchoServer";
}
public ThreadedEchoServer(int port, int connections) {
super(port, connections);
}
/** The new version of handleConnection starts a thread. This
* new thread will call back to the old version of
* handleConnection, resulting in the same server behavior
* in a multithreaded version. The thread stores the Socket
* instance since run doesn't take any arguments, and since
* storing the socket in an instance variable risks having
* it overwritten if the next thread starts before the run
* method gets a chance to copy the socket reference.
*/
public void handleConnection(Socket server) {
Connection connectionThread = new Connection(this, server);
connectionThread.start();
}
public void run() {
Connection currentThread =
(Connection)Thread.currentThread();
try {
super.handleConnection(currentThread.getSocket());
} catch(IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
}
}
}
/** This is just a Thread with a field to store a Socket object.
* Used as a thread-safe means to pass the Socket from
* handleConnection to run.
*/
class Connection extends Thread {
private Socket serverSocket;
public Connection(Runnable serverObject,
Socket serverSocket) {
super(serverObject);
this.serverSocket = serverSocket;
}
public Socket getSocket() {
return serverSocket;
}
}
EchoServer.java Creates a Web page showing all data sent from the client (browser).
import java.net.*;
import java.io.*;
import java.util.StringTokenizer;
/** A simple HTTP server that generates a Web page showing all
* of the data that it received from the Web client (usually
* a browser). To use this server, start it on the system of
* your choice, supplying a port number if you want something
* other than port 8088. Call this system server.com. Next,
* start a Web browser on the same or a different system, and
* connect to http://server.com:8088/whatever. The resultant
* Web page will show the data that your browser sent. For
* debugging in servlet or CGI programming, specify
* http://server.com:8088/whatever as the ACTION of your HTML
* form. You can send GET or POST data; either way, the
* resultant page will show what your browser sent.
*
* 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 EchoServer extends NetworkServer {
protected int maxRequestLines = 50;
protected String serverName = "EchoServer";
/** Supply a port number as a command-line
* argument. Otherwise, use port 8088.
*/
public static void main(String[] args) {
int port = 8088;
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
} catch(NumberFormatException nfe) {}
}
new EchoServer(port, 0);
}
public EchoServer(int port, int maxConnections) {
super(port, maxConnections);
listen();
}
/** Overrides the NetworkServer handleConnection method to
* read each line of data received, save it into an array
* of strings, then send it back embedded inside a PRE
* element in an HTML page.
*/
public void handleConnection(Socket server)
throws IOException{
System.out.println
(serverName + ": got connection from " +
server.getInetAddress().getHostName());
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
String[] inputLines = new String[maxRequestLines];
int i;
for (i=0; i\n" +
"\n" +
"\n" +
" \n" +
"\n" +
"\n" +
"\n" +
"
" + serverName +
" Results
\n" +
"Here is the request line and request headers\n" +
"sent by your browser:\n" +
"
");
}
// Print bottom of a standard Web page.
private void printTrailer(PrintWriter out) {
out.println
("
\n" +
"\n" +
"\n");
}
// Normal Web page requests use GET, so this server can simply
// read a line at a time. However, HTML forms can also use
// POST, in which case we have to determine the number of POST
// bytes that are sent so we know how much extra data to read
// after the standard HTTP headers.
private boolean usingPost(String[] inputs) {
return(inputs[0].toUpperCase().startsWith("POST"));
}
private void readPostData(String[] inputs, int i,
BufferedReader in)
throws IOException {
int contentLength = contentLength(inputs);
char[] postData = new char[contentLength];
in.read(postData, 0, contentLength);
inputs[++i] = new String(postData, 0, contentLength);
}
// Given a line that starts with Content-Length,
// this returns the integer value specified.
private int contentLength(String[] inputs) {
String input;
for (int i=0; iOverride this method in servers
* you write.
*
* This generic version simply reports the host that made
* the connection, shows the first line the client sent,
* and sends a single line in response.
*/
protected void handleConnection(Socket server)
throws IOException{
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
System.out.println
("Generic Network Server: got connection from " +
server.getInetAddress().getHostName() + "\n" +
"with first line '" + in.readLine() + "'");
out.println("Generic Network Server");
server.close();
}
/** Gets the max connections server will handle before
* exiting. A value of 0 indicates that server should run
* until explicitly killed.
*/
public int getMaxConnections() {
return(maxConnections);
}
/** Sets max connections. A value of 0 indicates that server
* should run indefinitely (until explicitly killed).
*/
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/** Gets port on which server is listening. */
public int getPort() {
return(port);
}
/** Sets port. You can only do before "connect" is
* called. That usually happens in the constructor.
*/
protected void setPort(int port) {
this.port = port;
}
}
SocketUtil.java Simplifies the creation of a PrintWriter and BufferedReader.
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));
}
}
Aug 25
Implementing a Server : Network Server
NetworkServerTest.java Establishes a network Server that listens for client requests on the port specified (command-line argument). Uses the following classes:
/** 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 NetworkServerTest {
public static void main(String[] args) {
int port = 8088;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
}
NetworkServer nwServer = new NetworkServer(port, 1);
nwServer.listen();
}
}
# NetworkServer.java A starting point for network servers.
import java.net.*;
import java.io.*;
/** A starting point for network servers. You'll need to
* override handleConnection, but in many cases listen can
* remain unchanged. NetworkServer 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 NetworkServer {
private int port, maxConnections;
/** Build a server on specified port. It will continue to
* accept connections, passing each to handleConnection until
* an explicit exit command is sent (e.g., System.exit) or
* the maximum number of connections is reached. Specify
* 0 for maxConnections if you want the server to run
* indefinitely.
*/
public NetworkServer(int port, int maxConnections) {
setPort(port);
setMaxConnections(maxConnections);
}
/** Monitor a port for connections. Each time one is
* established, pass resulting Socket to handleConnection.
*/
public void listen() {
int i=0;
try {
ServerSocket listener = new ServerSocket(port);
Socket server;
while((i++ < maxConnections) || (maxConnections == 0)) {
server = listener.accept();
handleConnection(server);
}
} catch (IOException ioe) {
System.out.println("IOException: " + ioe);
ioe.printStackTrace();
}
}
/** This is the method that provides the behavior to the
* server, since it determines what is done with the
* resulting socket. Override this method in servers
* you write.
*
* This generic version simply reports the host that made
* the connection, shows the first line the client sent,
* and sends a single line in response.
*/
protected void handleConnection(Socket server)
throws IOException{
BufferedReader in = SocketUtil.getReader(server);
PrintWriter out = SocketUtil.getWriter(server);
System.out.println
("Generic Network Server: got connection from " +
server.getInetAddress().getHostName() + "\n" +
"with first line '" + in.readLine() + "'");
out.println("Generic Network Server");
server.close();
}
/** Gets the max connections server will handle before
* exiting. A value of 0 indicates that server should run
* until explicitly killed.
*/
public int getMaxConnections() {
return(maxConnections);
}
/** Sets max connections. A value of 0 indicates that server
* should run indefinitely (until explicitly killed).
*/
public void setMaxConnections(int maxConnections) {
this.maxConnections = maxConnections;
}
/** Gets port on which server is listening. */
public int getPort() {
return(port);
}
/** Sets port. You can only do before "connect" is
* called. That usually happens in the constructor.
*/
protected void setPort(int port) {
this.port = port;
}
}
SocketUtil.java Simplifies the creation of a PrintWriter and BufferedReader.
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));
}
}
