Search code examples
javafilermiremote-accessjfilechooser

JFileChooser and RMI


i tried to build a FileChooser with java and RMI to browse the file system of a remote machine.

What I did until now is best shown in the following diagram. The exists() method-call is an example and all methods of RemoteFileView, RemoteFileSystemView and RemoteFile forward to the server.

enter image description here

In words: I build a RemoteFileView (extends FileView), RemoteFileSystemView (extends FileSystemView) and a RemoteFile (extends File) and overrode all methods of the super-classes except File.hashCode() and FileSystemView.createFileSystemRoot(File) (this method is protected in FileSystemView). All overridden methods call methods on the RMI-Server where the FileView- and FileSystemView from the server call the server-methods (like the JFileChooser would do). I get the FileView and the FileSystemView on the server side from a dummy instantiated JFileChooser.

So now what the system does:
- Start RMI-Server
- Start RMI-Client
- JFileChooser gets the RemoteFileView
- JFileChooser gets the RemoteFileSystemView
- JFileChooser gets all the RemoteFiles from the server and shows folders as well as files in the JFileChooser

So the behavior is good until now. And now the problem (where I can’t get rid of): The initial view of the JFileChooser (client) shows all Files of the home directory of the server. I can (per button click) switch to the parent directory until the system root (on windows for example the system drive „C:\“ ). From there (or from everywhere else) I can double-click on a folder to jump into it as long as this path exists on the client-system but the shown files and folders are from the server. If the path doesn’t exist on the client I can’t jump into it and browse this folder. So if anyone knows this behavior please help (I appreciate any solution :) ).

So I decided to code an own mouse listener that recognize double-clicks on the JFileChooser. But if I double-click on a folder (in the JFileChooser) nothing happens. If I highlight a folder (via click) and then double-click somewhere in the JFileChooser (not in the File-View or a button) the listener recognize my double-click and jumps into the highlighted folder (hope this is clear enough).

I think the FileView (on the JFileChooser) lies over the JFileChooser and should get it’s own listeners. Or I forgot something to code out.

The RMI-interface holds all methods which are called from the RemoteFileView, RemoteFileSystemView and the RemoteFile and from the behavior of the system this should be ok.

I can of course poste some codes as well as more informations about the whole program. Posting all codes would be too much I guess.

EDIT: As this question may be "too broad" the more concrete version (which may solve my problem): Which listener fires on double click a folder in the JFileChooser? Can this listener be removed or set?

EDIT2: I saw in this question: Repurposing JFileChooser that the JFileChooser fires on JFileChooser.APPROVE_SELECTION whenever a file is choosen by double click. So I implemented this code:

fileChooser.addActionListener(new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent e) {
    System.out.println("Some action");
    String command = e.getActionCommand();
    if (command.equals(JFileChooser.APPROVE_SELECTION)) {
      File file = fileChooser.getSelectedFile();
      fileChooser.setCurrentDirectory(file);
      fileChooser.rescanCurrentDirectory();
    }
  }
});

But unfortunately the action listener doesn't recognize any action inside the FileView (the component which shows the files) but does fire action events on button clicks (which I detected with the System.out..).


Solution

  • The problem as I described above are the components and their mouse listeners. So first you have to get your components and then add the listeners to it. So in a JFileChooser we got a JList and a JTable. Both views can be switched by button klick. The JList holds the files as well as the JTable.

    I found kind of solution here: https://community.oracle.com/thread/1350166?start=0&tstart=0

    So I used some codes from there and implemented my mouse listeners:

    The Listener for the JList:

    JList<?> list = SwingUtils.getDescendantOfType(JList.class, fileChooser, "Enabled", true);
    
    MouseListener listener = new MouseAdapter() {
    
      @Override
      public void mousePressed(MouseEvent e) {
        File file = fileChooser.getSelectedFile();
    
       if (e.getClickCount() == 2 && file != null) {
          if (e.getSource() == list) {
            // Do your stuff
            operateOnFile(file);
          } 
          else {
            // Default operation
          }
        }       
      }
    };
    
    list.addMouseListener(listener);
    

    And the listener for the JTable:

    final Container filePane = SwingUtilities.getAncestorOfClass(sun.swing.FilePane.class, list);
    
    filePane.addContainerListener(new ContainerAdapter() {
    
      @Override
      public void componentAdded(ContainerEvent e) {
        JTable table = SwingUtils.getDescendantOfType(JTable.class, fileChooser, "Enabled", true);
        if (table != null) {
          for (MouseListener l : table.getMouseListeners()) {
            if (l == listener) {
              return;
            }
          }          
          table.addMouseListener(listener);
        }
      }
    });
    

    With this solution I got the behavior I wanted.