Preventing a JTree to be expanded or collapsed

Use the TreeWillExpandListener interface!

The following example allows expanding of nodes, but prevents collapsing.

Main.java:

import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.event.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
 
public class Main extends JFrame
{
   public Main() {
      DefaultMutableTreeNode root = createNodes();
      JTree tree = new JTree(root);
 
      tree.addTreeWillExpandListener(new TreeWillExpandListener() {
         public void treeWillCollapse(TreeExpansionEvent event) 
                            throws ExpandVetoException 
         {
            // prevent collapsing
            throw new ExpandVetoException(event);
 
         }
         public void treeWillExpand(TreeExpansionEvent event) 
                            throws ExpandVetoException 
         {
            // do nothing
         }
      });
 
      getContentPane().add(new JScrollPane(tree));
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
   }
 
   public static DefaultMutableTreeNode createNodes() {
      DefaultMutableTreeNode root = new DefaultMutableTreeNode("Java");
      
      DefaultMutableTreeNode j2se = new DefaultMutableTreeNode("J2SE");
      DefaultMutableTreeNode j2ee = new DefaultMutableTreeNode("J2EE");
      DefaultMutableTreeNode j2me = new DefaultMutableTreeNode("J2ME");
 
      j2se.add(new DefaultMutableTreeNode("http://java.sun.com/j2se/"));
      j2ee.add(new DefaultMutableTreeNode("http://java.sun.com/j2ee/"));
      j2me.add(new DefaultMutableTreeNode("http://java.sun.com/j2me/"));
 
      root.add(j2se);
      root.add(j2ee);
      root.add(j2me);
 
      return root;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setSize(400, 400);
      main.setVisible(true);
   }
}

Disabling selection in my JTable

Look at the three lines of code in this working program to find out how to disallow any selection.

Main.java:

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));
      JScrollPane scrollPane = new JScrollPane(table);
 
      getContentPane().add(scrollPane);
 
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(0);
         }
      });
 
      // disable selection
      table.setRowSelectionAllowed(false);
      table.setColumnSelectionAllowed(false);
      table.setCellSelectionEnabled(false);
 
      pack();
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.show();
   }
}

Denying/allowing access to certain IP addresses in Tomcat

Use the Remote Address Filter Valve. [A valve, Tomcat only, is a Java class that preprocesses access requests. You can associate valves in server.xml to the containers engine, host and context.] It allows you to specify, at configuration time, whether or not requests coming from certain (sets of) IP addresses should be allowed or denied (using regular expressions). By default, all accesses are allowed. Look in server.xml for RemoteAddrValve.

eg.

   <Valve className="org.apache.catalina.valves.RemoteAddrValve" deny="127.0.0.*"/>

Setting the font on an 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.graphics.Font;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
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 Button Font 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);
      button1.setText("left");
      Font font1 = new Font(display, "courier", 10, 0);
      button1.setFont(font1);
      sizeControl(button1, 100, 30);   
      button1.addSelectionListener(selectionListener);
       
      Button button2 = new Button(buttonGroup, SWT.PUSH);
      button2.setText("center");
      Font font2 = new Font(display, "tahoma", 10, 0);
      button1.setFont(font2);
      sizeControl(button2, 100, 30);
      button2.addSelectionListener(selectionListener);
 
      Button button3 = new Button(buttonGroup, SWT.PUSH);
      button3.setText("right");
      Font font3 = new Font(display, "webdings", 10, 0);
      button3.setFont(font3);
      sizeControl(button3, 100, 30);
      button3.addSelectionListener(selectionListener);
      
      shell.open();
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
      display.dispose();
      font1.dispose();
      font2.dispose();
      font3.dispose();
   }
    
   public static void sizeControl(Control control, int width, int height) {
      GridData gridData = new GridData();   
      gridData.widthHint = width;
      gridData.heightHint = height;
      control.setLayoutData(gridData);
   }
}

Creating a list in SWT

Main.java:

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
 
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 List Demonstration");
      shell.setLayout(new GridLayout());
 
      String []items = {"Belgium", "The Netherlands", "France", "Germany", "Italy",
                        "Luxembourg", "Switzerland", "Austria", "Finland", "Iceland" };
       
      final List list = new List(shell, SWT.H_SCROLL | SWT.V_SCROLL);
      list.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL));
      list.setItems (items);
             
      shell.open();
       
      shell.addShellListener(new ShellAdapter() {
         public void shellClosed(ShellEvent se) {
            int[] indices = list.getSelectionIndices();
            System.out.println("Selected items:");
            for (int i=0; i<indices.length; i++) {
               System.out.println(list.getItem(indices[i]));   
            }
         }
      });      
 
      while (!shell.isDisposed()) {
         if (!display.readAndDispatch()) {
            display.sleep();
         }
      }
       
      display.dispose();
   }
    
   public static void recurseTree(TreeItem item) {
      System.out.println(item.getText() + "tChecked=" + item.getChecked());
      TreeItem[] treeItems = item.getItems(); 
      for (int i=0; i<treeItems.length; i++) {
         TreeItem treeItem = treeItems[i];
         recurseTree(treeItem);
      }   
   }
}

Renaming a file using the JNDI file service provider

Here’s an example:

import javax.naming.event.*;
import javax.naming.*;
import java.util.*;
import java.io.*;
  
public class Main
{
   public static void main(String []args) {
      try {
         Properties properties = new Properties();
         properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
         properties.put(Context.PROVIDER_URL, "file:///");
 
         InitialContext ctx = new InitialContext(properties);
 
         Context context = (Context) ctx.lookup("c:\temp\");
 
         context.rename("test.txt", "test1.txt");
 
         ctx.close(); 
      }
      catch(NamingException ne) {
         ne.printStackTrace();
      }
   }
}

Sending messages to a JMS queue

I used openjms to develop this example. Download it, start up the server (startup.sh/bat) and create a queue testqueue (admin.sh/bat).

The following example sends a TextMessage to the testqueue queue in PERSISTENT delivery mode, meaning that the JMS server will store the message on secondary storage to prevent loosing the message with server failures or crashes. The message stays there until delivered to all the consumers.

Main.java:

import javax.naming.*;
import java.util.*;
 
import javax.jms.*;
 
public class Main
{
   public static void main(String []args) throws Exception {
      // Load Context for OpenJMS
      Hashtable env = new Hashtable();
      env.put(Context.INITIAL_CONTEXT_FACTORY,"org.exolab.jms.jndi.rmi.RmiJndiInitialContextFactory");
      env.put(Context.PROVIDER_URL, "rmi://localhost:1099/JndiServer");
      Context ctx = new InitialContext(env);
  
      QueueConnectionFactory cnxFactory = (QueueConnectionFactory) ctx.lookup("JmsQueueConnectionFactory");
 
      Connection connection = ((QueueConnectionFactory) cnxFactory).createQueueConnection();
      QueueSession session = ((QueueConnection) connection).createQueueSession(
                                   false, Session.CLIENT_ACKNOWLEDGE);
      Queue queue = session.createQueue("testqueue");
      QueueSender sender = session.createSender(queue);
      sender.setDeliveryMode(javax.jms.DeliveryMode.PERSISTENT);
 
      TextMessage textMsg = session.createTextMessage();
      textMsg.setText("Hello world!");
      sender.send(textMsg);
      System.out.println("Message sent!");
  
      System.exit(1);
   }
}

Getting the process ID on Windows from Java

You will have to use JNI for this. Using the following code, I’ll create a DLL that provides the method getPid which will return the current process ID.

Pid.java:

public class Pid {
   public native int getPid();
   
   public int getProcessID() {
      try {
         return getPid();
      }
      catch(UnsatisfiedLinkError e) {
         e.printStackTrace();
      }
      
      return -1;
   }
   
   public static void main(String args[])
   {
      try {
         System.loadLibrary("Pid");
      }
      catch(java.lang.UnsatisfiedLinkError e) {
         e.printStackTrace();
      }

      Pid pid = new Pid();
      System.out.println(pid.getProcessID());
   }
}

Compile and run javah on it to create the pid.h header file:

javah Pid

It generates the C header file Pid.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Pid */

#ifndef _Included_Pid
#define _Included_Pid
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Pid
 * Method:    getPid
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_Pid_getPid
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

The C code that allows to get the current process ID:

#include <windows.h>
#include <stdio.h>
#include <iphlpapi.h>
#include "pid.h"

JNIEXPORT jint JNICALL Java_Pid_getPid
  (JNIEnv *env, jobject object) {
   return (int) GetCurrentProcessId();
}

I used cygwin to develop a Windows DLL from this in the following way:

gcc -mno-cygwin -I/usr/include -Ic:/jdk1.3.1/include -Ic:/jdk1.3.1/include/win32
 -shared Pid.c -Wl,--add-stdcall-alias -o Pid.dll

This DLL now allows you to get the process ID of your current Java app. Here’s an example:

C:experimentsjavapid>java Pid
3844
C:experimentsjavapid>java Pid
3876

For those who don’t have cygwin installed or want to start using it right away, here’s the library:

Pid.dll

Detecting a deadlock with ThreadMBean in JDK 1.5

This example shows how to use the ThreadMBean class in JDK 1.5 to detect a deadlock. ThreadMBean is a management class (package java.lang.management) that provides functionality to query the thread system of the JVM.

The example creates three threads A, B and C which end up in a deadly embrace: A waits for a lock that B holds, B waits for a lock that C holds and C waits for a lock that A holds. The method findMonitorDeadlockedThreads returns the list of Thread ids involved in the deadlock.

FindDeadlock.java:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMBean;
import java.lang.management.ThreadState;
 
public class FindDeadlock
{
   Object a = new Object();
   Object b = new Object();
   Object c = new Object();
   
   public static void main(String []args) {
      final FindDeadlock fd = new FindDeadlock();
   
      Thread t1 = new Thread() {
         public void run() {
            while (true) { fd.m1(); }
         }
      };
      
      Thread t2 = new Thread() {
         public void run() {
            while (true) { fd.m2(); }
         }
      };
      
      Thread t3 = new Thread() {
         public void run() {
            while (true) { fd.m3(); }
         }
      };      
      
      t1.setName("First thread");
      t2.setName("Second thread");
      t3.setName("Third thread");
      
      t1.start();
      t2.start();
      t3.start();
      
      // give the time for the threads to go into a deadlock
      try { Thread.sleep(1000); } catch(Exception e) { } 
      
      ThreadMBean mbean = ManagementFactory.getThreadMBean();
      long[] threads = mbean.findMonitorDeadlockedThreads();
      if (threads != null) {
         for (int i=0; i<threads.length; i++) { 
            ThreadInfo threadInfo = mbean.getThreadInfo(threads[i]);
            ThreadState threadState = mbean.getThreadState(threads[i]);
            
            System.out.print(threadInfo.getThreadName() + "(" + threadState + ") is waiting for ");
            System.out.print(threadInfo.getLockOwnerName() + " to release ");
            System.out.println("the lock " + threadInfo.getLockName());
         }
      }
   }
   
   public void m1() {
      synchronized(a) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(b) {
            System.out.println("m1 got through");
         }
      }
   }
   
   public void m2() {
      synchronized(b) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(c) {
            System.out.println("m2 got through");
         }
      }
   }
   
   public void m3() {
      synchronized(c) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(a) {
            System.out.println("m3 got through");
         }
      }
   }   
}

outputs:

Third thread(Blocked) is waiting for First thread to release the lock java.lang.Object@d9f9c3
First thread(Blocked) is waiting for Second thread to release the lock java.lang.Object@1a46e30
Second thread(Blocked) is waiting for Third thread to release the lock java.lang.Object@3e25a5