Example of TreeTable

The example program about TreeTable discussed in Sun’s article Creating TreeTables: Part 2 adds unnecessary complexity. The following is a much simpler one and will get you started much quicker.

Prerequisite: Download src.zip from the above url and compile the with both programs presented here.

Main.java:

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
 
public class Main extends JFrame {
   protected MyTreeTableModel  model;
   protected JTreeTable        treeTable;
 
   public Main() {
      super("Main");
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      model     = new MyTreeTableModel();
      treeTable = new JTreeTable(model);
 
      getContentPane().add(new JScrollPane(treeTable));
 
      try {
         UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
         SwingUtilities.updateComponentTreeUI(this);
      }
      catch(Exception e) {
         e.printStackTrace();
      }
 
      pack();
      show();
   }
 
   public static void main(String[] args) {
      new Main();
   }
}

MyTreeTableModel.java:

import java.io.IOException;
import java.io.File;
import java.util.Date;
import java.util.Stack;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;
import java.util.*;
 
public class MyTreeTableModel extends AbstractTreeTableModel {
 
   // Names of the columns.
   static protected String[] cNames = {"Column 1", "Column 2", 
                                       "Column 3", "Column 4"};
   // Types of the columns.
   static protected Class[]  cTypes = { TreeTableModel.class, String.class, 
                                        String.class, String.class };
   static Entry rootEntry;  
 
   /******** Entry class represents the parent and leaf nodes **********/
   static class Entry {
      private String name; 
      private boolean isLeaf;
      private Vector children = new Vector();
 
      public Entry(String name, boolean isLeaf) {
         this.name = name;
         this.isLeaf = isLeaf;
      }
 
      public Vector getChildren() {
         return children;
      }
 
      public boolean isLeaf() {
         return isLeaf;
      }
 
      public String getName() {
         return name;
      }
 
      public String toString() {
         return name;
      }
   }
 
   static {
      rootEntry = new Entry("rootentry", false);
      rootEntry.getChildren().addElement(new Entry("test1", true));
      rootEntry.getChildren().addElement(new Entry("test2", true));

      Entry subEntry1 = new Entry("subentry1", false);
      subEntry1.getChildren().addElement(new Entry("test3", true));
      subEntry1.getChildren().addElement(new Entry("test4", true));
      Entry subEntry2 = new Entry("subentry2", false);
      subEntry2.getChildren().addElement(new Entry("test5", true));
      subEntry2.getChildren().addElement(new Entry("test6", true));
      rootEntry.getChildren().addElement(subEntry1);
      rootEntry.getChildren().addElement(subEntry2); 
   }
   /*************************************/
 
   public MyTreeTableModel() { 
      super(rootEntry);
   }
 
   public int getChildCount(Object node) { 
      if (!((Entry) node).isLeaf()) {
         return ((Entry) node).getChildren().size();
      }
      return 0;
   }
 
   public Object getChild(Object node, int i) { 
      return ((Entry) node).getChildren().elementAt(i);
   }
 
   public boolean isLeaf(Object node) {
      return ((Entry) node).isLeaf();
   }
 
   public int getColumnCount() {
      return cNames.length;
   }
 
   public String getColumnName(int column) {
      return cNames[column];
   } 
 
   public Class getColumnClass(int column) {
      return cTypes[column];
   }
 
   public Object getValueAt(Object node, int column) {
      switch(column) {
         case 0:
            return node;
         case 1:
            return "value1";
         case 2:
            return "value2";
         case 3:
            return "value3";
      }
   
      return null; 
   }
}

Writing a dynamic proxy class

The following example uses a dynamic proxy class to keep track of how much time it takes to execute a method.

Two classes are implemented: JMSTransporter and TibcoTransporter, both implementing the interface Transporter.

interface Transporter {  
   public void sendMessage(String message);
}
 
class TibcoTransporter implements Transporter {
   public void sendMessage(String message) {
      ...
   }
}
 
class JMSTransporter implements Transporter {
   public void sendMessage(String message) {
      ...
   }
}

Suppose we need to do some performance tests to see how long each transporter takes to perform its task. The typical way of doing this is to record a timestamp in the beginning of the method and at the end and printing out the difference:

   long start = System.currentTimeMillis();
 
   .. perform job
 
   long stop = System.currentTimeMillis();
   System.out.println("Total time it took: " + (stop - start));

We would have to do that for the TibcoTransporter as well as the JMSTransporter. It also uglifies the code, makes it harder to maintain (remove when it goes in production) and may introduce bugs. You could also write a wrapper around it, but this is a tedious task and would require you to do this for every interface.

Since JDK1.3, you can simplify this task using a dynamic proxy class. A dynamic proxy class is a class that implements a list of interfaces at runtime. An instance of this class can handle method invocations of the interface(s) and dispatches them to the object that implements the interface.

Writing a proxy class is simple: implement the InvocationHandler interface and its method

   public Object invoke(Object proxy, Method method, Object[] args)            
                     throws Throwable; 

To instantiate a proxy object:

   Proxy.newProxyInstance(ClassLoader loader,
                          Class[] interfaces,
                          InvocationHandler h) 

In our example, the proxy class TimerProxy is created. All method invocations to the interfaces that were specified when instantiating the proxy object with newProxyInstance are dispatched to the TimerProxy.

Main.java:

import java.lang.reflect.*;
 
interface Transporter
{
   public void sendMessage(String message);
}
 
class TibcoTransporter implements Transporter
{
   public void sendMessage(String message) {
      // let's assume the message takes 1 second to send 
      // using Tiboc RendezVous
      try {
         Thread.sleep(1000);
      }
      catch(InterruptedException e) {
      }
      System.out.println("Message '" + message + "' sent with the TibcoTransporter");
   }
}
 
class JMSTransporter implements Transporter
{
   public void sendMessage(String message) {
      // let's assume the message takes 2 seconds to send 
      // using a JMS implementation
      try {
         Thread.sleep(2000);
      }
      catch(InterruptedException e) {
      }
      System.out.println("Message '" + message + "' sent with the JMSTransporter");
   }
}
   
public class Main
{
   public static void main(String []args) {
      TibcoTransporter tibcoTransporter = new TibcoTransporter();

      Transporter transporter1 = (Transporter) TimerProxy.newInstance(new TibcoTransporter());
      transporter1.sendMessage("Hi");

      Transporter transporter2 = (Transporter) TimerProxy.newInstance(new JMSTransporter());
      transporter2.sendMessage("Hi");
   }
}

class TimerProxy implements InvocationHandler
{
   private Object obj;
 
   public TimerProxy(Object obj) {
      this.obj = obj;
   }
  
   public static Object newInstance(Object obj) {
      return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                                    obj.getClass().getInterfaces(),
                                    new TimerProxy(obj));
   }
 
   public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
   {
      Object result = null;
      long start, stop;
      System.out.println("- Entering " + m.getName() + " in class " + obj.getClass());
      start = System.currentTimeMillis();
      try {
         result = m.invoke(obj, args);
      }
      catch(InvocationTargetException e) {
         throw e.getTargetException();
      }
      catch(Exception e) {
         throw new RuntimeException(e.getMessage());
      }
      finally {
         stop = System.currentTimeMillis();
         System.out.println("- Total time it took: " + (stop - start));
      }
      System.out.println("- Exiting " + m.getName() + " in class " + obj.getClass());
 
      return result;
   }
}

outputs:

- Entering sendMessage in class class TibcoTransporter
Message 'Hi' sent with the TibcoTransporter
- Total time it took: 1002
- Exiting sendMessage in class class TibcoTransporter
- Entering sendMessage in class class JMSTransporter
Message 'Hi' sent with the JMSTransporter
- Total time it took: 2003
- Exiting sendMessage in class class JMSTransporter

Other uses for a dynamic proxy are logging, parameter validation, access control, error handling, …

For more information on Dynamic Proxy Classes, check here

Using the MemoryRealm

The following example will create a web application containing a jsp that will behave based on who is logged in. The possible users that can be logged in will be defined in an xml file called tomcat-users.xml located in the [TOMCAT-HOME]/conf directory.

This example will recognize two types of custom defined roles: GOLD and SILVER roles. Every user will be assigned one or both roles.

1. Create the following xml file in the [TOMCAT-HOME]/conf directory: tomcat-users.xml (or add the user tags to the existing tomcat-users.xml file):

<tomcat-users>
  <user name="gary"    password="yrag"   roles="gold"/>
  <user name="alicia"  password="aicila" roles="gold"/>
  <user name="john"    password="nhoj"   roles="silver"/>
  <user name="joris"   password="siroj"  roles="gold,silver"/>
</tomcat-users>

2. The JSP is as simple as it can be. It prints out the user that is logged in and prints out to which role it belongs.

confidential.jsp:

<html>
<body>
Hi, <%=request.getUserPrincipal().getName()%><br><br>
<%
   if (request.isUserInRole("gold")) {
%>
      You have the GOLD role<br>
<%
   }
   if (request.isUserInRole("silver")) {
%>
      You have the SILVER role<br>
<%
   }
%>
</body>
</html>

3. Create the WEB-INF/web.xml deployment descriptor.

<?xml version="1.0" encoding="ISO-8859-1"?>
 
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">
 
<web-app>
   <security-constraint>
      <web-resource-collection>
         <web-resource-name>admin</web-resource-name>
         <url-pattern>*.jsp</url-pattern>
      </web-resource-collection>
      <auth-constraint>
         <role-name>gold</role-name>
         <role-name>silver</role-name>
      </auth-constraint>
   </security-constraint>
   <login-config>
      <auth-method>BASIC</auth-method>
      <realm-name>Log In</realm-name>
   </login-config>
</web-app>

This deployment descriptor specifies that only users with roles gold or silver are authorized to access the *.jsp resources. The method of authorization is BASIC. Other possible authorization methods are DIGEST and FORM (see other Q/A’s for examples).

4. Now package everything up in a web application loginexample1.war:

C:loginexample1>jar -cvf loginexample1.war *
added manifest
adding: confidential.jsp(in = 275) (out= 160)(deflated 41%)
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/web.xml(in = 673) (out= 328)(deflated 51%)

and drop loginexample1.war into the /webapps directory.

5. Start up Catalina and point your browser to http://localhost:8080/loginexample1/confidential.jsp.

Because a security constraint is defined in web.xml, specifying that only gold and silver roles can access all jsp pages, and because BASIC authentication is specified, the following window will popup to ask for the username and password:

Try one of the entries in tomcat-users.xml. Notice that you cannot log out, except by closing the browser window.

Using a CheckBox in SWT

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Shell;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT Checkbox Demonstration");
      shell.setLayout(new GridLayout());
 
      Group buttonGroup = new Group(shell, SWT.NONE);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 3;
      buttonGroup.setLayout(gridLayout);
      buttonGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            Button button = ((Button) event.widget);
            System.out.print(button.getText());
            System.out.println(" selected = " + button.getSelection());
         };
      };
                  
      Button button1 = new Button(buttonGroup, SWT.CHECK);
      button1.setText("orange");
      button1.addSelectionListener(selectionListener);
      Button button2 = new Button(buttonGroup, SWT.CHECK);
      button2.setText("pear");
      button2.addSelectionListener(selectionListener);
      Button button3 = new Button(buttonGroup, SWT.CHECK);
      button3.setText("apple");
      button3.addSelectionListener(selectionListener);
      
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
}

Creating an SWT FileDialog

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
 
public class Main { 
   static Display display;
   static Shell shell;
   static Color color;
    
   public static void main(String[] args) {
      display = new Display();
      shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 400, 200);
      shell.setText("SWT FileDialog Demonstration");
      shell.setLayout(new GridLayout());
 
      final Group buttonGroup = new Group(shell, SWT.NONE);
      GridLayout gridLayout = new GridLayout();
      gridLayout.numColumns = 3;
      buttonGroup.setLayout(gridLayout);
      buttonGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
       
      final Button directoryDialogButton = new Button(buttonGroup, SWT.PUSH);
      directoryDialogButton.setText("FileDialog");
      Label label1 = new Label(buttonGroup, SWT.NONE);
      label1.setText("File selected:");
      final Label label2 = new Label(buttonGroup, SWT.NONE);      
      label2.setText("");
 
      final String [] filterNames = { "All Files", "JPG Files", "GIF Files" };
      final String [] filterExtensions = { "*.*", "*.jpg", "*.gif" };
 
      SelectionListener selectionListener = new SelectionAdapter () {
         public void widgetSelected(SelectionEvent event) {
            FileDialog dialog = new FileDialog(shell, SWT.MODELESS);
            dialog.setFileName ("esuslogo.gif");
            dialog.setFilterNames (filterNames);
            dialog.setFilterExtensions (filterExtensions);
            dialog.setText("Select Image File");
            String result = dialog.open();
            label2.setText("" + result);
            buttonGroup.layout();
         };
      };   
        
      directoryDialogButton.addSelectionListener(selectionListener);
       
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      if (color != null && !color.isDisposed()) {
         color.dispose();
      }
      display.dispose();
   }
}

Creating an SWT Text(Area)

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
 
public class Main {
   public static void main(String[] args) {
      Display display = new Display();
      Shell shell = new Shell(display);
 
      // pos x, pos y, width, height
      shell.setBounds(200, 200, 300, 200);
      shell.setText("SWT Text Demonstration");
      shell.setLayout(new GridLayout());
 
      shell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
      Text text = new Text(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.WRAP);
      text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
       
      text.setText("Did you know..." +
                   "nn" +
                   "It is impossible to lick your elbow." +
                   "nnnnnnnnnnnnnnn" +
                   "Over 75% of people who read thisn" +
                   "will try to lick their elbow.");
       
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
       
      display.dispose();
   }
}

Catching a specific SIGNAL/Interrupt in Java

You can use the undocumented class sun.misc.Signal. But beware of using the Sun packages.

This program allows you to catch any of the following signals:

   Windows:
      	ABRT	SIGABRT
	FPE 	SIGFPE
    	SEGV	SIGSEGV
	INT	SIGINT
	TERM	SIGTERM
	ILL	SIGILL


   Solaris/Linux:
	HUP	SIGHUP
	INT	SIGINT
	QUIT	SIGQUIT
	ILL	SIGILL
	TRAP	SIGTRAP
	ABRT	SIGABRT
	IOT	SIGIOT (*)
	EMT	SIGEMT (*)
	FPE	SIGFPE
	KILL	SIGKILL
	BUS	SIGBUS
	SEGV	SIGSEGV
	SYS	SIGSYS
	PIPE	SIGPIPE
	ALRM	SIGALRM
	TERM	SIGTERM
	STKFLT	SIGSTKFLT
	USR1	SIGUSR1
	USR2	SIGUSR2
	CHLD	SIGCHLD
	PWR	SIGPWR
	WINCH	SIGWINCH
	URG	SIGURG
	POLL	SIGPOLL
	IO	SIGIO
	STOP	SIGSTOP
	TSTP	SIGTSTP
	CONT	SIGCONT
	TTIN	SIGTTIN
	TTOU	SIGTTOU
	VTALRM	SIGVTALRM
	PROF	SIGPROF
	XCPU	SIGXCPU
	XFSZ	SIGXFSZ
	UNUSED	SIGUNUSED
	SWI	SIGSWI

The example program (Linux/Solaris) demonstrates to catch and perform a System.exit only with a SIGTERM. A SIGHUP will not cause the program to exit.

Main.java:

import sun.misc.Signal;
import sun.misc.SignalHandler;
import java.lang.reflect.*;
 
public class Main
{
   public static void main(String []args) {
      DebugSignalHandler.listenTo("HUP");
      DebugSignalHandler.listenTo("INT");
      DebugSignalHandler.listenTo("KILL");
      DebugSignalHandler.listenTo("TERM");
 
      while (true) {
         try {
            Thread.sleep(1000);
         }
         catch(InterruptedException e) {
         }
      }
   }
}
 
class DebugSignalHandler implements SignalHandler
{
   public static void listenTo(String name) {
      Signal signal = new Signal(name);
      Signal.handle(signal, new DebugSignalHandler());
   }

   public void handle(Signal signal) {
      System.out.println("Signal: " + signal);
      if (signal.toString().trim().equals("SIGTERM")) {
         System.out.println("SIGTERM raised, terminating...");
         System.exit(1);
      }
   }
}

Dynamically add JARs from an application’s lib directory

This example assumes you have the JDBC mm.mysql driver residing in an ext subdirectory.

Main.java:

import java.util.*;
import java.net.*;
import java.io.*;
import java.sql.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      ClassLoader cl = loadExt();
      if (cl != null) {
         cl.loadClass("org.gjt.mm.mysql.Driver").newInstance();
         System.out.println("mysql driver successfully loaded!");
         Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/esus", "USER", "PASS");
 
         //. . .
      }
   }
 
   public static URLClassLoader loadExt() {
      try {
         Vector urls = new Vector();
         File file = new File("ext");
         String[] list = file.list();
         for (int i=0; i<list.length; i++) {
            if (list[i].endsWith(".jar")) {
               urls.add(new URL("file:" + file.getName() + "/" + list[i]));
            }
         }
         return new URLClassLoader((URL[]) urls.toArray( new URL[] { } ));
      } catch ( java.net.MalformedURLException me ) { 
         me.printStackTrace();
      }
 
      return null;
   }
}

Changing the color of one JTable cell

Main.java:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.awt.*;
 
public class Main extends JFrame {
   public Main() {
      super("TableModel Demonstration");
  
      // create our own custom TableModel
      WineTableModel wineModel = new WineTableModel();
      JTable table = new JTable(wineModel);
 
      // since we're using values of floats and boolean here, we need
      // to set the cell renderer for every column. 
      for (int i =0; i<wineModel.getColumnCount();i++) {
         table.setDefaultRenderer(table.getColumnClass(i), new WineCellRenderer());
      }
       
      // add rows to our TableModel, each row is represented as a Wine object
      wineModel.addWine(new Wine("Chateau Meyney, St. Estephe", "1994", 18.75f, true));
      wineModel.addWine(new Wine("Chateau Montrose, St. Estephe", "1975", 54.25f, true));
      wineModel.addWine(new Wine("Chateau Gloria, St. Julien", "1993", 22.99f, false));
      wineModel.addWine(new Wine("Chateau Beychevelle, St. Julien", "1970", 61.63f, false));
      wineModel.addWine(new Wine("Chateau La Tour de Mons, Margeaux", "1975", 57.03f, true));
      wineModel.addWine(new Wine("Chateau Brane-Cantenac, Margeaux", "1978", 49.92f, false));
 
      // create the scroll pane and add the table to it. 
      JScrollPane scrollPane = new JScrollPane(table);
 
      // add the scroll pane to this window.
      getContentPane().add(scrollPane, BorderLayout.CENTER);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public static void main(String[] args) {
      Main main = new Main();
      main.pack();
      main.setVisible(true);
   }
}
 
// a simple object that holds data about a particular wine
class Wine {
   private String  name;
   private String  vintage;
   private float   price;
   private boolean inStock;
 
   public Wine(String name, String vintage, float price, boolean inStock) {
      this.name = name;
      this.vintage = vintage;
      this.price = price;
      this.inStock = inStock;
   }
 
   public String getName()     { return name; }
   public String getVintage()  { return vintage; }
   public float  getPrice()    { return price; } 
   public boolean getInStock() { return inStock; }
 
   public String toString() { 
      return "[" + name + ", " + vintage + ", " + price + ", " + inStock + "]"; }
}
 
class WineTableModel extends AbstractTableModel {
   // holds the strings to be displayed in the column headers of our table
   final String[] columnNames = {"Name", "Vintage", "Price", "In stock?"};
 
   // holds the data types for all our columns
   final Class[] columnClasses = {String.class, String.class, Float.class, Boolean.class};
 
   // holds our data
   final Vector data = new Vector();
  
   // adds a row
   public void addWine(Wine w) {
      data.addElement(w);
      fireTableRowsInserted(data.size()-1, data.size()-1);
   }
 
   public int getColumnCount() {
      return columnNames.length;
   }
         
   public int getRowCount() {
      return data.size();
   }
 
   public String getColumnName(int col) {
      return columnNames[col];
   }
 
   public Class getColumnClass(int c) {
      return columnClasses1;
   }
 
   public Object getValueAt(int row, int col) {
      Wine wine = (Wine) data.elementAt(row);
      if (col == 0)      return wine.getName();
      else if (col == 1) return wine.getVintage();
      else if (col == 2) return new Float(wine.getPrice());
      else if (col == 3) return new Boolean(wine.getInStock());
      else return null;
   }
 
   public Object getValueAtRow(int row) {
      Wine wine = (Wine) data.elementAt(row);
      return wine;
   }
 
   public boolean isCellEditable(int row, int col) {
      return false;
   }
}
 
class WineCellRenderer extends DefaultTableCellRenderer {
   public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
   {
      WineTableModel wtm = (WineTableModel) table.getModel();
      Wine wine = (Wine) wtm.getValueAtRow(row);
 
      if (column == 3 && wine.getInStock() == false) {
         setBackground(Color.red);
      }
      else {
         setBackground(Color.white);
      }
 
      return super.getTableCellRendererComponent(table, value, isSelected, 
                                                 hasFocus, row, column);
   }
}

Setting the a connect timeout on an URLConnection

JDK1.5 allows you to set connect and read timeouts on URLConnection (HttpURLConnection, etc.).

Here is an example:

Main.java:

import java.net.*;

public class Main
{
   public static void main(String []args) throws Exception {
      if (args.length != 1) {
         System.err.println("Usage: java Main <URL>");
         System.exit(0);
      }
          
      URL url = new URL(args[0]);
      URLConnection connection = url.openConnection();
 
      connection.setConnectTimeout(5000);
      connection.connect();
   }
}