Dynamically change the Look and Feel of a Swing application

Invoke UIManager.setLookAndFeel and provide it with the new Look and Feel class. Force components to reflect this new look by calling SwingUtilities.updateComponentTreeUI. All components in the tree of which you specify the parent component will be asked to use the new Look And Feel. Also do a call to frame.pack to ensure the window to be sized to fit the preferred size and layouts of its subcomponents. Here’s an example:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main implements ActionListener
{ 
   JFrame frame;
   
   public Main() {
      frame = new JFrame("Table one row selection demonstration"); 
      frame.addWindowListener( new WindowAdapter() { 
         public void windowClosing(WindowEvent e) { 
            System.exit(0); 
         } 
      }); 
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("Look and Feel");
      JMenuItem menuItem1 = new JMenuItem("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
      JMenuItem menuItem2 = new JMenuItem("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
      JMenuItem menuItem3 = new JMenuItem("javax.swing.plaf.metal.MetalLookAndFeel");
      menu.add(menuItem1);
      menu.add(menuItem2);
      menu.add(menuItem3);
      menuItem1.addActionListener(this);
      menuItem2.addActionListener(this);
      menuItem3.addActionListener(this);
      menuBar.add(menu);
      frame.setJMenuBar(menuBar);
 
      JTable table = new JTable(35, 3); 
  
      table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
 
      frame.getContentPane().add(new JScrollPane(table)); 
 
      frame.pack(); 
      frame.show(); 
   } 
 
   public void actionPerformed(ActionEvent ae) {
      try {
         UIManager.setLookAndFeel(ae.getActionCommand());
         SwingUtilities.updateComponentTreeUI(frame);
         frame.pack();
      }
      catch(Exception e) {
         System.out.println(e);
      }
   }
 
   public static void main(String[] args) {
      Main main = new Main();
   }
}

Getting the attributes of an XML Node

Use a NamedNodeMap. The following example shows you how to print out all elements for the tag customer.

customer.xml (!!remove the space between ? and xml):

<? xml version="1.0" encoding="UTF-8"?>
<customers>
   <customer id="C12345" type="prio1">
      <name>Joris Van den Bogaert</name>
      <address>
         <addressline>Handelskaai 3</addressline>
         <zip>1000</zip>
         <location>Brussels</location>
         <country>BELGIUM</country>
      </address>
   </customer>
</customers>

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customer.xml"));
 
         NodeList nodeList = doc.getElementsByTagName("customer");
         Node node = nodeList.item(0);
  
         NamedNodeMap attributes = node.getAttributes();
         for (int i=0; i<attributes.getLength(); i++) {
            Node attribute = attributes.item(i);
            System.out.println(attribute.getNodeName() + " = " + attribute.getNodeValue());
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

outputs:

id = C12345
type = prio1

To get a specific attribute, you can use the method getNamedItem.

Main.java:

import org.w3c.dom.*;
 
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;
 
import java.io.*;
   
public class Main
{
   public static void main(String []args) {
      Document doc;
  
      try {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         DocumentBuilder db = dbf.newDocumentBuilder();
         doc = db.parse(new File("customer.xml"));
 
         NodeList nodeList = doc.getElementsByTagName("customer");
         Node node = nodeList.item(0);
  
         NamedNodeMap attributes = node.getAttributes();
 
         Node custId = attributes.getNamedItem("id");
         Node custType = attributes.getNamedItem("type");
         System.out.println("id   = " + custId.getNodeValue());
         System.out.println("type = " + custType.getNodeValue());
         }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

Get the IP address of the client connecting to a Servlet

Call the method getRemoteAddr on the HttpServletRequest instance.

MainServlet.java:

import javax.servlet.http.*;
import javax.servlet.*;
 
import java.io.*;
 
public class MainServlet extends HttpServlet
{
   public void doGet (HttpServletRequest request,
                      HttpServletResponse response)
      throws ServletException, IOException
   {
      String ip = request.getRemoteAddr();
      
      response.setContentType("text/html");
      PrintWriter out = response.getWriter();
 
      out.println("<html><body>");
      out.println(ip);
      out.println("</body></html>");
      out.close();
   }
}

Saving binary data (eg. images) in a database table

As an example, I created the following table:

mysql> create table images (imageid int(10) not null auto_increment, 
name varchar(30), data blob, length int(6), primary key(imageid));
Query OK, 0 rows affected (0.12 sec)
 
mysql> desc images;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| imageid | int(10)     |      | PRI | NULL    | auto_increment |
| name    | varchar(30) | YES  |     | NULL    |                |
| length  | int(6)      | YES  |     | NULL    |                |
| data    | blob        | YES  |     | NULL    |                |
+---------+-------------+------+-----+---------+----------------+

Main.java:

import java.util.*;
import java.text.*;
import java.sql.*;
import java.io.*;  
 
public class Main {
   public static void main(String []args) throws Exception {
      try {
         Class.forName("org.gjt.mm.mysql.Driver").newInstance();
         Connection conn = DriverManager.getConnection("jdbc:mysql://192.168.0.1/esus", 
                                                       "joris",
                                                       "mypass");
 
         File[] files = new File(".").listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
               if (name.endsWith(".gif")) {
                  return true;
               }
               return false;
            }
         });
 
         for (int i=0; i<files.length; i++) {
            FileInputStream fis=new FileInputStream(files[i]);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte buf[]=new byte[1024];
            int length=-1;
            while((length=fis.read(buf))!=-1) {
               baos.write(buf,0,length);
            }
 
            PreparedStatement insertStmt = conn.prepareStatement(
                                          "INSERT INTO images (name, length, data) " +
                                          "VALUES (?, ?, ?)");
            insertStmt.setString(1, files[i].getName());
            insertStmt.setInt(2, (int) files[i].length());
            insertStmt.setBytes(3, baos.toByteArray());
            insertStmt.execute();
 
            fis.close();
            baos.close();
        }
      }
      catch(Exception e) {
         e.printStackTrace();
      }
   } 
}

Getting a list of environment variables

You can’t anymore. There used to be a method called getenv(String) in java.lang.System but it’s been deprecated since
1.1.8. The only thing you can do now is to use the -D properties flag on the command line when you start your program.

java -Dproperty=value myapp.class

Where property is the name of the property and value is the value you want to as sign it.

You can then retrieve the value of the property using:

getProperty("property");

If you still want to allow the user to set environment variables you can always use them as the value for the property in the startup batch file or shell script like this:

Windows:

   SET ENVVVAR=value
   java -Dproperty=%ENV_VAR% myapp.class

Unix:

   ENV_VAR=value
   export ENV_VAR
   java -Dproperty=$ENV_VAR myapp.class

Performance gain of using NIO channels as opposed to regular streams for doing file I/O

To test things out, I wrote a couple small Java programs to copy a file:

CopyFile1.java: uses the old approach using BufferedInput/BufferedOutputStreams with the default buffer size of 2048 bytes
CopyFile2.java: uses the NIO libraries with different buffer sizes
CopyFile3.java: uses the NIO FileChannel method transferTo

CopyFile1.java uses BufferedInputStream and BufferedOutputStream. If you look at the source code for these files, the default buffer is an array of 2048 bytes. The first version of the NIO CopyFile2 program is also set to use an internal buffer of 2048 bytes. Other tests have been done with larger buffer sizes. As expected, the more buffer space allocated, the higher the performance (at a cost of more memory usage).

The result of copying the Java SDK file j2sdk-1_4_0-win.exe(37Meg) using JDK1.2.2, JDK1.3 and JDK1.4 on a Win2000/450Mhz machine is plotted here:


(All numbers are seconds)

CopyFile1.java:

import java.io.*;
 
public class CopyFile1
{
   public static void main(String []args) throws IOException {
      if (args.length != 2) {
         System.err.println("Usage: java CopyFile1 source dest");
         System.exit(1);
      }
 
      String source = args[0];
      String dest = args[1];
 
      long start = System.currentTimeMillis();
 
      BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));
 
      int k;
      while ((k = bis.read()) != -1) {
         bos.write(k);
      }
   
      bis.close();
      bos.close();
 
      long stop = System.currentTimeMillis();
 
      System.out.println("Total time it took to copy: " + (stop - start) + "ms.");
   }
}

CopyFile2.java:

import java.nio.*;
import java.nio.channels.*;
import java.io.*;
 
public class CopyFile2
{
   public static void main(String []args) throws IOException {
      if (args.length != 2) {
         System.err.println("Usage: java CopyFile2 source dest");
         System.exit(1);
      }
 
      String source = args[0];
      String dest = args[1];
 
      long start = System.currentTimeMillis();
 
      FileInputStream fis = new FileInputStream(source);
      FileOutputStream fos = new FileOutputStream(dest);
      
      FileChannel channelIn = fis.getChannel();
      FileChannel channelOut = fos.getChannel();
 
      ByteBuffer buffer = ByteBuffer.allocateDirect(2048); 
 
      int n = channelIn.read(buffer);
      while (n > -1) {
         buffer.flip();
         channelOut.write(buffer);
         buffer.clear();
  
         n = channelIn.read(buffer);
      }      
 
      long stop = System.currentTimeMillis();
 
      System.out.println("Total time it took to copy: " + (stop - start) + "ms.");
   }
}

CopyFile3.java:

import java.nio.*;    
import java.nio.channels.*;    
import java.io.*;        
 
public class CopyFile3 
{        
   public static void main(String args[]) throws IOException {                
      if (args.length != 2) {
         System.err.println("Usage: java CopyFile3 source dest");
         System.exit(1);
      }             
 
      String source = args[0];
      String dest = args[1];
 
      long start = System.currentTimeMillis();
 
      FileInputStream fis = new FileInputStream(source);            
      FileOutputStream fos = new FileOutputStream(dest);            
      
      FileChannel channelIn = fis.getChannel();
      FileChannel channelOut = fos.getChannel();
 
      channelIn.transferTo(0, channelIn.size(), channelOut);                
 
      channelIn.close();            
      channelOut.close();            
 
      long stop = System.currentTimeMillis();
 
      System.out.println("Total time it took to copy: " + (stop - start) + "ms.");
   }    
}

Underlining a cell in a JTable

The easiest way is to use HTML in your text, check How do I create a JLabel with the text underlined?

But here’s a code sample that does not make use of the HTML feature. It underlines all Integers in the JTable whose values are between 1970 and 1980.

Main.java:

import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame 
{
   public Main() {
      super("Table example, Wines from Bordeaux");
 
      Object[][] tabledata = {
            { "Chateau Meyney, St. Estephe", 	   new Integer(1994), "$18.75"},
            { "Chateau Montrose, St. Estephe", 	   new Integer(1975), "$54.25" },
            { "Chateau Gloria, St. Julien", 	   new Integer(1993), "$22.99" },
            { "Chateau Beychevelle, St. Julien",   new Integer(1970), "$61.63" },
            { "Chateau La Tour de Mons, Margeaux", new Integer(1975), "$57.03" },
            { "Chateau Brane-Cantenac, Margeaux",  new Integer(1978), "$49.92" },
      };
 
      String columnheaders[] = { "Wine", "Vintage", "Price" };
 
      JTable table = new JTable(tabledata, columnheaders);
      table.setPreferredScrollableViewportSize(new Dimension(500, 70));
 
      UnderlineTableCellRenderer renderer = new UnderlineTableCellRenderer();
      table.setDefaultRenderer(Object.class, renderer);
      table.setRowHeight(30);
 
      JScrollPane scrollPane = new JScrollPane(table);
      getContentPane().add(scrollPane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      pack();
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}
 
class UnderlineTableCellRenderer extends DefaultTableCellRenderer 
{
   public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                                                  boolean hasFocus, int row, int column) {
      if (value instanceof Integer) {
         Integer amount = (Integer) value;
         if (amount.intValue() > 1970 && amount.intValue() < 1980) {
            return new UnderlinedJLabel("" + amount.intValue());
         }
      }
 
      return super.getTableCellRendererComponent
                      (table, value, isSelected, hasFocus, row, column);
   }
}
 
class UnderlinedJLabel extends JLabel
{
   public UnderlinedJLabel() {
   }
 
   public UnderlinedJLabel(Icon image) {
      super(image);
   }
 
   public UnderlinedJLabel(Icon image, int horizontalAlignment) {
      super(image, horizontalAlignment);
   }
 
   public UnderlinedJLabel(String text) {
      super(text);
   }
 
   public UnderlinedJLabel(String text, Icon icon, int horizontalAlignment) {
      super(text, icon, horizontalAlignment);
   }
 
   public UnderlinedJLabel(String text, int horizontalAlignment) {
      super(text, horizontalAlignment);
   }
 
   public void paint(Graphics g) {
      super.paint(g);
      underline(g);
   }
 
   protected void underline(Graphics g) {
      Insets insets = getInsets();
      FontMetrics fm = g.getFontMetrics();
      Rectangle textR = new Rectangle();
      Rectangle viewR = new Rectangle(
                                  insets.left, 
                                  insets.top, 
                                  getWidth() - (insets.right + insets.left), 
                                  getHeight() - (insets.bottom + insets.top));
  
      // compute and return location of the icons origin,
      // the location of the text baseline, and a possibly clipped
      // version of the compound label string.  Locations are computed 
      // relative to the viewR rectangle.
      String text = SwingUtilities.layoutCompoundLabel(
                         this,                        // this JLabel
                         fm,                          // current FontMetrics
                         getText(),                   // text
                         getIcon(),                   // icon
                         getVerticalAlignment(),      
                         getHorizontalAlignment(),
                         getVerticalTextPosition(),
                         getHorizontalTextPosition(), 
                         viewR,                       
                         new Rectangle(),             // don't care about icon rectangle
                         textR,                       // resulting text locations
                         getText() == null ? 0 : ((Integer)UIManager.get("Button.textIconGap")).intValue());
 
      // draw line
      int textShiftOffset = ((Integer) UIManager.get("Button.textShiftOffset")).intValue();
      g.fillRect(textR.x +
                 textShiftOffset - 4,
                 textR.y + fm.getAscent() + textShiftOffset + 2,
                 textR.width, 
                 1);
   }
}

Writing your own Tomcat Valve

You can extend from org.apache.catalina.valves.ValveBase and implement the method invoke. The following example just prints out is has been called and invokes the next Valve.

MyValve.java:

import javax.servlet.http.*;
import javax.servlet.*;
import java.util.*;
import java.io.*;
import org.apache.catalina.valves.*;
import org.apache.catalina.*;
 
public class MyValve extends ValveBase
{
   /**
    * The descriptive information related to this implementation.
    */
   private static final String info = "MyValve/1.0";
 
   /**
    * Return descriptive information about this Valve implementation.
    */
   public String getInfo() {
      return (info);
   }
 
   public void invoke(Request request, Response response, ValveContext context)
                             throws IOException, ServletException {
      // Skip logging for non-HTTP requests and responses
      if (!(request instanceof HttpRequest) ||
          !(response instanceof HttpResponse)) {
         context.invokeNext(request, response);
         return;
      }
 
      HttpRequest httpRequest   = (HttpRequest) request;
      HttpResponse httpResponse = (HttpResponse) response;
      HttpServletRequest httpServletRequest   = (HttpServletRequest) httpRequest.getRequest();
      HttpServletResponse httpServletResponse = (HttpServletResponse) httpResponse.getResponse();
 
      System.out.println("nnnMyValve invokednnn");
 
      // continue processing the request
      context.invokeNext(request, response);
   }
 
   public String toString() {
      StringBuffer sb = new StringBuffer();
      sb.append("MyValve[");
      if (container != null) {
         sb.append(container);
      }
      sb.append("]");
      return sb.toString();
   }
}

Compile it with catalina.jar and servlet.jar in your classpath and place it in /server/classes.

Making a flat SWT button

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, 400, 200);
      shell.setText("SWT Flat Button 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.PUSH | SWT.FLAT);
      button1.setText("orange");
      button1.addSelectionListener(selectionListener);
       
      Button button2 = new Button(buttonGroup, SWT.PUSH | SWT.FLAT);
      button2.setText("pear");
      button2.addSelectionListener(selectionListener);
 
      Button button3 = new Button(buttonGroup, SWT.PUSH | SWT.FLAT);
      button3.setText("apple"); 
      button3.addSelectionListener(selectionListener);
       
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
   }
}