Simple NetBeans Module to Search Jar File for Specified Class

The following blog entry will take you through the creation of a NetBean 6.1 (although the principal is the same for other versions) Plug-in Module that will allow you to search all Jar files in a specified directory structure for a given Class name or part there of. On completion of this short tutorial you will have created a new Toolbar button and Menu item that will open a Search tab within the editor window. This will allow you to enter the Class Name to search for and the starting directory. If you would simply like a copy of the NBM then it can be found on the NetBeans Plugin Portal at http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=15286.

Resources

Module Overview


If you have been developing Java for a while you have probably come across the situation where you need to find a class you have used but it does not exist in your CLASSPATH. Well to resolve this I build a simple NetBeans Plugin (originally in NB 5) and have since upgraded it to NB 6.1.

The Jar Class Search Plugin, below, adds a new Menu item to the Toolbar Edit Menu and a new button to the Edit Toolbar. When either of these is selected the Jar Search tab will be opened within the Edit area of Netbeans. The user can then type in the name (or part of the name) of the Class they wish to search for and the starting directory. In addition the you can choose to search just the specified directory or recursively through all sub-directories and display all the jars that contain the specified Class or just the first.

Once the criteria have been entered you will be able to select Search and the Plugin will Search all Jars found for the Class and display the results in the Table.

Jar Class Search

Creating the Module


To create the Module you will need to follow the steps below.
  1. File->New->Project->NetBeans Modules->Module

    Create 1

  2. Next
  3. Name and Location Page
    1. Project Name: JarClassSearch

      Create 2
  4. Next
  5. Module Configuration Page
    1. Code Name Base : com.aph.jar.search
    2. Module display Name : JarClassSearch
    3. Localizing Bundle : com/aph/jar/search/Bundle.properties
    4. XML Layer : com/aph/jar/search/layer.xml

      Create 3
  6. Finish

Supporting Files

Once the project has been create we will need to copy a number of utility classes and icons into the project structure. These will be used to associate the desired icon with the menu action and also process the searching of the directory and Jars to find those containing the class. All source for these can be found in the project Zip in the resources section below. We now need to create three new packages:
  • com.aph.jar.search.util.file
  • com.aph.jar.search.util.swing
  • com.aph.jar.search.icon
Copy some appropriate icons into the new icon package, you will need:
  • jar_view.png
  • jar_view16.png
  • jar_view24.png
So that the Plugin has a number of specific sizes. NetBeans will specifically look for the icon name 16 and 24 during the creation of the Action (Button). In the util.file package add create the following java files.
These class are fairly self explanatory and simply group together a number of methods I have used previously.

Windows Components and Actions

Now that we have created the associated files that will search through the specified directory and all jar files found we need to create a Windows Component and Action that will use them. This is achieved as follows:
  1. Right Click on the com.aph.jar.search package and select New->Windows Component

    New Component 1

  2. Basic Settings Page
    1. Window Position : editor

      Window component

  3. Next
  4. Name, Icon and Location Page
    1. Class Name Profix : JarClassSearch
    2. Icon : Browse to chosen icon (jar_view.png)

      Window component

  5. Finish
This will create the following files:
  • JarClassSearchAction.java (Example Action Class)
  • JarClassSearchTopComponent.java (The actual window that will be displayed)
  • JarClassSearchTopcomponentSettings.xml
  • JarClassSearchTopComponentWstcref.xml

We now need to modify the JarClassSearchTopComponent.java so that it displays the fields we need as follows:

Windows Component

  1. Open JarClassSearchTopComponent.java
  2. Add JPanel, from the Palette, to the TopComponent.
    1. Name : topLevelPanel
    2. Layout : BowLayout - Page Axis
    3. Add JPanel
      1. Name : searchCriteriaPanel
      2. Layout : GridLayout - 3 Columns
      3. Border : Etched
      4. Add JLabel
        1. Text : Class Name :
      5. Add JTextField
        1. Name : tfClassname
        2. Text : String
        3. Maximum Size ; [2147483647, 25]
      6. Add JLabel
        1. Text : <Blank Text>
      7. Add JLabel
        1. Text : Start Directory
      8. Add JTextField
        1. Name : tfSearchRoot
        2. Text : /
        3. Maximum Size : [2147483647, 25]
      9. Add JButton
        1. Name : btnBrowse
        2. Text : Browse
      10. Add JLabel
        1. Text : <Blank Text>
      11. Add JPanel
        1. Layout : BoxLayout - Line Axis
        2. Add JCheckBox
          1. Name : cbRecursive
          2. Text : Recursive
        3. Add JCheckBox
          1. Name : cbShowAll
          2. Text : Show All
      12. Add JButton
        1. Name : btnSearch
        2. Text : Search
    4. Add JPanel
      1. Name : resultPanel
      2. Layout : BoxLayout - Page Axis
      3. Border : Etched
      4. Add JTable (This will automatically create a JScrollPane)
        1. Name : tblJars
  3. Create Button Actions for the two button (Double Click on them) and modify the code as follows.

New Properties / Methods

// Properties
protected String classname = "";
protected String rootDirectoryName = "";
protected boolean recursive = false;
protected boolean showAll = true;
protected JarTableModel jarTableModel = new JarTableModel();
protected SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");

protected class SearchJarRunThread implements Runnable {

    public void run() {
        try {
            clearJarTable();
            JarUtils jarUtils = new JarUtils();
            File[] files = jarUtils.getSubFiles(rootDirectoryName, recursive);
            Object[] row = new String[JarTableModel.COLUMNS];
            String classnameInJar = null;
            if (files != null) {
                for (int i = 0; i < files.length; i++) {
                    if (jarUtils.getExtension().equals(jarUtils.getExtension(files[i]))) {
                        if (jarUtils.isFileInArchieve(classname, files[i].getAbsolutePath())) {
                            classnameInJar = jarUtils.getClassnameInArchive();
                            System.out.println(files[i].getAbsolutePath() + "      (" + classnameInJar + ")");
                            if (classnameInJar.endsWith(".class")) {
                                row = new String[JarTableModel.COLUMNS];
                                row[0] = files[i].getAbsolutePath();
                                row[1] = classnameInJar.replaceAll("/", ".");
                                row[2] = sdf.format(new Date(files[i].lastModified()));
                                row[3] = Long.toString(files[i].length());
                                jarTableModel.addRow(row);
                                if (!showAll) {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
            Exceptions.printStackTrace(ex);
        }
    }
}
// Methods
private void postInitComponents() {
    // Set Layouts
    //searchPanel
    searchCriteriaPanel.setLayout(new SpringLayout());
    SpringUtilities.makeCompactGrid(searchCriteriaPanel,
            3, 3, // Rows, Columns
            0, 0, // Initial X, Initial Y
            10, 10);   // X Pad, YPad

    //topLevelPanel
    topLevelPanel.setLayout(new SpringLayout());
    SpringUtilities.makeCompactGrid(topLevelPanel,
            2, 1,
            0, 10,
            10, 10);
    // Set Table Model
    tblJars.setModel(jarTableModel);
    clearJarTable();
      tblJars.getSelectionModel().addListSelectionListener(new RowListener());

    // TopComponent
    setLayout(new SpringLayout());
    SpringUtilities.makeCompactGrid(this,
            1, 1,
            0, 0,
            0, 0);

    // Get Settings
    String classname = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.CLASSNAME_KEY, "");
    String searchRoot = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.SEARCH_ROOT_KEY, "");
    String recursiveString = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.RECURSIVE_KEY, Boolean.toString(JarClassSearchConstantsInterface.RECURSIVE_DEFAULT));
    String showAllString = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.SHOWALL_KEY, Boolean.toString(JarClassSearchConstantsInterface.SHOWALL_DEFAULT));

    tfClassname.setText(classname);
    tfSearchRoot.setText(searchRoot);
    cbRecursive.setSelected(Boolean.parseBoolean(recursiveString));
    cbShowAll.setSelected(Boolean.parseBoolean(showAllString));

}

protected void clearJarTable() {
    for (int i = jarTableModel.getRowCount() - 1; i >= 0; i--) {
        jarTableModel.removeRow(i);
    }
}

Button Action Code

private void btnBrowseActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
    javax.swing.JFileChooser fileChooser = new JFileChooser(tfSearchRoot.getText());
    fileChooser.setMultiSelectionEnabled(false);
    fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
        tfSearchRoot.setText(fileChooser.getSelectedFile().getAbsolutePath());
    }

}

private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
    recursive = cbRecursive.isSelected();
    showAll = cbShowAll.isSelected();
    classname = tfClassname.getText().trim();
    rootDirectoryName = tfSearchRoot.getText().trim();

    // Save current values as last used
    Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.CLASSNAME_KEY, tfClassname.getText());
    Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.SEARCH_ROOT_KEY, tfSearchRoot.getText());
    Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.RECURSIVE_KEY, Boolean.toString(cbRecursive.isSelected()));
    Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.SHOWALL_KEY, Boolean.toString(cbShowAll.isSelected()));

    SearchJarRunThread runThread = new SearchJarRunThread();
    RequestProcessor.getDefault().post(runThread);

}


Constructor Change

private JarClassSearchTopComponent() {
    initComponents();
    setName(NbBundle.getMessage(JarClassSearchTopComponent.class, "CTL_JarClassSearchTopComponent"));
    setToolTipText(NbBundle.getMessage(JarClassSearchTopComponent.class, "HINT_JarClassSearchTopComponent"));
    setIcon(Utilities.loadImage(ICON_PATH, true));
    postInitComponents();
}

You will notice from the above code that we need to additional classes and these should be created in the com.aph.jar.search.util.swing package.

Menu / Button Action

Now we have created the display component for the Module we need to add the Action that will be displayed in the Edit Menu and as a Button in the Edit Toolbar. This can be done in two ways.
  1. Edit the layer.xml and associated files to add the TopComponentAction
  2. Add a new Action and copy the code from the example action.
We will choose the second option.
  1. Delete the JarClassSearchAction.java (Copy Code first)
  2. Right Click the top level package and New-Action

    Action 1

  3. Action Type
    1. Always Enabled

      Action 2

  4. Next
  5. GUI Registration
    1. Category : Edit
    2. Global Menu Item : checked
    3. Menu : Edit
    4. Global Toolbar Button : Checked
    5. Toolbar : Edit

      Action 3

  6. Next
  7. Name, Icon and Location
    1. Class Name JarClassSearchAction
    2. Display Name : Jar Class Search
    3. Icon : Browse to your Icon

      Action 4

  8. Finish
  9. This will create the JarClassSearchAction.java file and modify the layer.xml and Bundle.properties.
  10. Take the previously copied performAction method and replace the one generated as follows.

    package com.aph.jar.search;

    import org.openide.util.HelpCtx;
    import org.openide.util.NbBundle;
    import org.openide.util.actions.CallableSystemAction;
    import org.openide.windows.TopComponent;

    public final class JarClassSearchAction extends CallableSystemAction {

        public void performAction() {
            TopComponent win = JarClassSearchTopComponent.findInstance();
            win.open();
            win.requestActive();
        }

        public String getName() {
            return NbBundle.getMessage(JarClassSearchAction.class, "CTL_JarClassSearchAction");
        }

        @Override
        protected String iconResource() {
            return "com/aph/jar/search/icon/jar_view.png";
        }

        public HelpCtx getHelpCtx() {
            return HelpCtx.DEFAULT_HELP;
        }

        @Override
        protected boolean asynchronous() {
            return false;
        }
    }

The Project can now be Cleaned, Built and Tested. Once you are happy it all works then a NBM can be generated and installed into your NetBeans instance.




Comments:

Thank you. Great module.

Posted by Toni on June 20, 2010 at 03:01 AM GMT #

wow1

Posted by it's really interesting on March 27, 2011 at 06:37 PM GMT #

Post a Comment:
Comments are closed for this entry.
About

As a member of the Oracle A-Team we specialise in enabling and supporting the Oracle Fusion Middleware communities.

Search

Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today