Java/Design Pattern/Router Pattern
Router Pattern in Java
//[C] 2002 Sun Microsystems, Inc.---
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.io.Serializable;
import java.rmi.Naming;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class RunRouterPattern {
public static void main(String[] arguments) {
System.out.println("Example for the Router pattern");
System.out
.println("This code same will create a series of GUIs, and use");
System.out
.println(" the Router pattern to map message notifications between");
System.out
.println(" them. In this code example, the Router will send messages");
System.out
.println(" between the GUI clients based on the following mapping:");
System.out.println();
System.out.println("\tGUI # 1:\tGUI #2\tGUI #3");
System.out.println("\tGUI # 2:\tGUI #1\tGUI #4");
System.out.println("\tGUI # 3:\tGUI #1\tGUI #4");
System.out.println("\tGUI # 4:\tGUI #1\tGUI #2\tGUI #3\tGUI #4");
System.out.println();
System.out.println("Running the RMI compiler (rmic)");
try {
Process p1 = Runtime.getRuntime().exec("rmic Router");
Process p2 = Runtime.getRuntime().exec("rmic RouterClient");
p1.waitFor();
p2.waitFor();
} catch (IOException exc) {
System.err
.println("Unable to run rmic utility. Exiting application.");
System.exit(1);
} catch (InterruptedException exc) {
System.err
.println("Threading problems encountered while using the rmic utility.");
}
System.out.println("Starting the rmiregistry");
System.out.println();
Process rmiProcess = null;
try {
rmiProcess = Runtime.getRuntime().exec("rmiregistry");
Thread.sleep(15000);
} catch (IOException exc) {
System.err
.println("Unable to start the rmiregistry. Exiting application.");
System.exit(1);
} catch (InterruptedException exc) {
System.err
.println("Threading problems encountered when starting the rmiregistry.");
}
System.out.println("Creating the Router object");
System.out.println();
Router mainRouter = new Router();
InputKey keyOne = new InputKey();
InputKey keyTwo = new InputKey();
InputKey keyThree = new InputKey();
InputKey keyFour = new InputKey();
System.out.println("Creating the four RouterGui objects");
System.out.println();
RouterGui first = new RouterGui(keyOne);
RouterGui second = new RouterGui(keyTwo);
RouterGui third = new RouterGui(keyThree);
RouterGui fourth = new RouterGui(keyFour);
System.out.println("Creating GUI OutputChannel lists for the Router");
System.out.println();
OutputChannel[] subscriptionListOne = { second.getOutputChannel(),
third.getOutputChannel() };
OutputChannel[] subscriptionListTwo = { first.getOutputChannel(),
fourth.getOutputChannel() };
OutputChannel[] subscriptionListThree = { first.getOutputChannel(),
second.getOutputChannel(), third.getOutputChannel(),
fourth.getOutputChannel() };
mainRouter.addRoute(keyOne, subscriptionListOne);
mainRouter.addRoute(keyTwo, subscriptionListTwo);
mainRouter.addRoute(keyThree, subscriptionListTwo);
mainRouter.addRoute(keyFour, subscriptionListThree);
first.createGui();
second.createGui();
third.createGui();
fourth.createGui();
}
}
class Message implements Serializable {
private InputChannel source;
private String message;
public Message(InputChannel source, String message) {
this.source = source;
this.message = message;
}
public InputChannel getSource() {
return source;
}
public String getMessage() {
return message;
}
}
interface OutputChannel extends Remote {
public void sendMessage(Message message) throws RemoteException;
}
interface Receiver {
public void receiveMessage(Message message);
}
class Router implements OutputChannel {
private static final String ROUTER_SERVICE_NAME = "router";
private HashMap links = new HashMap();
public Router() {
try {
UnicastRemoteObject.exportObject(this);
Naming.rebind(ROUTER_SERVICE_NAME, this);
} catch (Exception exc) {
System.err.println("Error using RMI to register the Router " + exc);
}
}
public synchronized void sendMessage(Message message) {
Object key = message.getSource();
OutputChannel[] destinations = (OutputChannel[]) links.get(key);
new RouterWorkThread(message, destinations);
}
public void addRoute(InputChannel source, OutputChannel[] destinations) {
links.put(source, destinations);
}
private class RouterWorkThread implements Runnable {
private OutputChannel[] destinations;
private Message message;
private Thread runner;
private RouterWorkThread(Message newMessage,
OutputChannel[] newDestinations) {
message = newMessage;
destinations = newDestinations;
runner = new Thread(this);
runner.start();
}
public void run() {
for (int i = 0; i < destinations.length; i++) {
try {
destinations[i].sendMessage(message);
} catch (RemoteException exc) {
System.err.println("Unable to send message to "
+ destinations[i]);
}
}
}
}
}
class RouterClient implements OutputChannel {
private static final String ROUTER_CLIENT_SERVICE_PREFIX = "routerClient";
private static final String ROUTER_SERVER_MACHINE_NAME = "localhost";
private static final String ROUTER_SERVER_SERVICE_NAME = "router";
private static int clientIndex = 1;
private String routerClientServiceName = ROUTER_CLIENT_SERVICE_PREFIX
+ clientIndex++;
private OutputChannel router;
private Receiver receiver;
public RouterClient(Receiver newReceiver) {
receiver = newReceiver;
try {
UnicastRemoteObject.exportObject(this);
Naming.rebind(routerClientServiceName, this);
String url = "//" + ROUTER_SERVER_MACHINE_NAME + "/"
+ ROUTER_SERVER_SERVICE_NAME;
router = (OutputChannel) Naming.lookup(url);
} catch (Exception exc) {
System.err.println("Error using RMI to register the Router " + exc);
}
}
public void sendMessageToRouter(Message message) {
try {
router.sendMessage(message);
} catch (RemoteException exc) {
}
}
public void sendMessage(Message message) {
receiver.receiveMessage(message);
}
public String toString() {
return routerClientServiceName;
}
}
class RouterGui implements ActionListener, Receiver {
private static int instanceCount = 1;
private RouterClient routerClient;
private JFrame mainFrame;
private JButton exit, clearDisplay, sendMessage;
private JTextArea display;
private JTextField inputTextField;
private InputChannel inputChannel;
public OutputChannel getOutputChannel() {
return routerClient;
}
public RouterGui(InputChannel newInputChannel) {
inputChannel = newInputChannel;
routerClient = new RouterClient(this);
}
public void createGui() {
mainFrame = new JFrame("Demonstration for the Router pattern - GUI #"
+ instanceCount++);
Container content = mainFrame.getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
JPanel displayPanel = new JPanel();
display = new JTextArea(10, 40);
JScrollPane displayArea = new JScrollPane(display);
display.setEditable(false);
displayPanel.add(displayArea);
content.add(displayPanel);
JPanel dataPanel = new JPanel();
dataPanel.add(new JLabel("Message:"));
inputTextField = new JTextField(30);
dataPanel.add(inputTextField);
content.add(dataPanel);
JPanel controlPanel = new JPanel();
sendMessage = new JButton("Send Message");
clearDisplay = new JButton("Clear");
exit = new JButton("Exit");
controlPanel.add(sendMessage);
controlPanel.add(clearDisplay);
controlPanel.add(exit);
content.add(controlPanel);
sendMessage.addActionListener(this);
clearDisplay.addActionListener(this);
exit.addActionListener(this);
inputTextField.addActionListener(this);
mainFrame.addWindowListener(new WindowCloseManager());
mainFrame.pack();
mainFrame.setVisible(true);
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == sendMessage) {
sendMessage();
} else if (source == inputTextField) {
sendMessage();
} else if (source == clearDisplay) {
clearDisplay();
} else if (source == exit) {
exitApplication();
}
}
private class WindowCloseManager extends WindowAdapter {
public void windowClosing(WindowEvent evt) {
exitApplication();
}
}
private void exitApplication() {
System.exit(0);
}
private void clearDisplay() {
inputTextField.setText("");
display.setText("");
}
private void sendMessage() {
String data = inputTextField.getText();
routerClient.sendMessageToRouter(new Message(inputChannel, data));
inputTextField.setText("");
}
public void receiveMessage(Message message) {
display.append(message.getMessage() + "\n");
}
}
class InputKey implements InputChannel {
private static int nextValue = 1;
private int hashVal = nextValue++;
public int hashCode() {
return hashVal;
}
public boolean equals(Object object) {
if (!(object instanceof InputKey)) {
return false;
}
if (object.hashCode() != hashCode()) {
return false;
}
return true;
}
}
interface InputChannel extends Serializable {
}