display.containers.FileManager.java Source code

Java tutorial

Introduction

Here is the source code for display.containers.FileManager.java

Source

package display.containers;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Container;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.*;
import java.awt.image.*;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.plaf.BorderUIResource;
import javax.swing.tree.*;
import javax.swing.table.*;
import javax.swing.filechooser.FileSystemView;

import javax.imageio.ImageIO;

import model.Project;
import model.ServerInfo;

import org.apache.commons.io.FileUtils;

import daemon.DecryptDaemon;
import daemon.NiftiDaemon;
import dao.MySQLProjectDAO;
import dao.ProjectDAO;
import dao.project.AcquisitionDateDAO;
import dao.project.DicomImageDAO;
import dao.project.MySQLAcquisitionDateDAO;
import dao.project.MySQLDicomImageDAO;
import dao.project.MySQLNiftiImageDAO;
import dao.project.MySQLPatientDAO;
import dao.project.MySQLProtocolDAO;
import dao.project.MySQLSerieDAO;
import dao.project.NiftiImageDAO;
import dao.project.PatientDAO;
import dao.project.ProtocolDAO;
import dao.project.SerieDAO;
import display.MainWindow;
import display.containers.viewer.ViewerPanel;
import es.vocali.util.AESCrypt;

import settings.SystemSettings;
import settings.UserProfile;
import settings.WindowManager;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.regex.Pattern;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import java.net.URL;
import display.imageprocessing.*;

/**
A basic File Manager.  Requires 1.6+ for the Desktop & SwingWorker
classes, amongst other minor things.
    
Includes support classes FileTableModel & FileTreeCellRenderer.
    
@TODO Bugs
<li>Still throws occasional AIOOBEs and NPEs, so some update on
the EDT must have been missed.
<li>Fix keyboard focus issues - especially when functions like
rename/delete etc. are called that update nodes & file lists.
<li>Needs more testing in general.
    
@TODO Functionality
<li>Implement Read/Write/Execute checkboxes
<li>Implement Copy
<li>Extra prompt for directory delete (camickr suggestion)
<li>Add File/Directory fields to FileTableModel
<li>Double clicking a directory in the table, should update the tree
<li>Move progress bar?
<li>Add other file display modes (besides table) in CardLayout?
<li>Menus + other cruft?
<li>Implement history/back
<li>Allow multiple selection
<li>Add file search
    
@author Andrew Thompson
@version 2011-06-01
@see http://stackoverflow.com/questions/6182110
@license LGPL
*/
public class FileManager {

    private static boolean stopAction;
    /** Used to open/edit/print files. */
    private Desktop desktop;
    /** Provides nice icons and names for files. */
    private FileSystemView fileSystemView;

    /** currently selected File. */
    private File currentDir;

    /** Main GUI container */
    private DefaultTreeModel treeModel;
    private MainWindow parentFrame;

    /** Directory listing */
    private JTable table;
    private JProgressBar progressBar;
    /** Table model for File[]. */
    private FileTableModel fileTableModel;
    private ListSelectionListener listSelectionListener;
    private boolean cellSizesSet = false;
    private int rowIconPadding = 6;
    private boolean continueAction;

    /** Attributs basiques **/
    private int mode; //mode definit le fonctionnement du filemanager
    private JPopupMenu Pmenu;
    private JMenuItem twitem;
    private JMenuItem tlitem;
    private JMenuItem changeProjectitem;
    private JMenuItem renameProjectitem;
    private JMenuItem processitem;

    public FileManager(MainWindow parent, Path defdir) {
        setCurrentDir(defdir.toFile());
        parentFrame = parent;
        continueAction = true;
        setMode(0);
    }

    /**
     * Le mode definit le fonctionnement du filemanager
     * 
     * Mode 0 = explorateur simple (defaut)
     * Mode 1 = explorateur workspace sur le serveur distant (n'affiche que les workspace autorises)
     * Mode 2 = explorateur serveur partie sauvegarde (NRI-DICOM, NRI-ANALYSE)
     * @param parent
     * @param defdir
     * @param mode : mode de fonctionnement
     */
    public FileManager(MainWindow parent, Path defdir, int mode) {
        this(parent, defdir);
        setMode(mode);
    }

    public FileManager(MainWindow parent) {
        setCurrentDir(new File(System.getProperty("user.home")));
        parentFrame = parent;
        continueAction = true;
        setMode(0);
    }

    public Container getPane() {
        //if (gui==null) {

        fileSystemView = FileSystemView.getFileSystemView();
        desktop = Desktop.getDesktop();

        JPanel detailView = new JPanel(new BorderLayout(3, 3));
        //fileTableModel = new FileTableModel();

        table = new JTable();
        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        table.setAutoCreateRowSorter(true);
        table.setShowVerticalLines(false);
        table.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                if (e.getClickCount() >= 2) {
                    Point p = e.getPoint();
                    int row = table.convertRowIndexToModel(table.rowAtPoint(p));
                    int column = table.convertColumnIndexToModel(table.columnAtPoint(p));
                    if (row >= 0 && column >= 0) {
                        mouseDblClicked(row, column);
                    }
                }
            }
        });
        table.addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent arg0) {

            }

            @Override
            public void keyReleased(KeyEvent arg0) {
                if (KeyEvent.VK_DELETE == arg0.getKeyCode()) {
                    if (mode != 2) {
                        parentFrame.setLock(true);
                        parentFrame.getProgressBarPanel().setVisible(true);
                        Thread t = new Thread(new Runnable() {

                            @Override
                            public void run() {
                                try {
                                    deleteSelectedFiles();
                                } catch (IOException e) {
                                    JOptionPane.showMessageDialog(parentFrame, "Error during the deletion.",
                                            "Deletion error", JOptionPane.ERROR_MESSAGE);
                                    WindowManager.mwLogger.log(Level.SEVERE, "Error during the deletion.", e);
                                } finally {
                                    parentFrame.setLock(false);
                                    refresh();
                                    parentFrame.getProgressBarPanel().setVisible(false);
                                }
                            }
                        });
                        t.start();

                    } else {
                        if (UserProfile.CURRENT_USER.getLevel() == 3) {
                            parentFrame.setLock(true);
                            parentFrame.getProgressBarPanel().setVisible(true);
                            Thread delThread = new Thread(new Runnable() {

                                @Override
                                public void run() {
                                    int[] rows = table.getSelectedRows();
                                    int[] columns = table.getSelectedColumns();
                                    for (int i = 0; i < rows.length; i++) {
                                        if (!continueAction) {
                                            continueAction = true;
                                            return;
                                        }
                                        int row = table.convertRowIndexToModel(rows[i]);
                                        try {
                                            deleteServerFile(row);
                                        } catch (Exception e) {
                                            WindowManager.mwLogger.log(Level.SEVERE, "Error during the deletion.",
                                                    e);
                                        }
                                    }
                                    refresh();
                                    parentFrame.setLock(false);
                                    parentFrame.getProgressBarPanel().setVisible(false);
                                }
                            });
                            delThread.start();

                        }
                    }
                }
            }

            @Override
            public void keyPressed(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }
        });
        table.getSelectionModel().addListSelectionListener(listSelectionListener);
        JScrollPane tableScroll = new JScrollPane(table);
        Dimension d = tableScroll.getPreferredSize();
        tableScroll.setPreferredSize(new Dimension((int) d.getWidth(), (int) d.getHeight() / 2));
        detailView.add(tableScroll, BorderLayout.CENTER);

        // the File tree
        DefaultMutableTreeNode root = new DefaultMutableTreeNode();
        treeModel = new DefaultTreeModel(root);
        table.getRowSorter().addRowSorterListener(new RowSorterListener() {

            @Override
            public void sorterChanged(RowSorterEvent e) {
                ((FileTableModel) table.getModel()).fireTableDataChanged();
            }
        });

        // show the file system roots.
        File[] roots = fileSystemView.getRoots();
        for (File fileSystemRoot : roots) {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode(fileSystemRoot);
            root.add(node);
            //showChildren(node);
            //
            File[] files = fileSystemView.getFiles(fileSystemRoot, true);
            for (File file : files) {
                if (file.isDirectory()) {
                    node.add(new DefaultMutableTreeNode(file));
                }
            }
            //
        }
        JScrollPane treeScroll = new JScrollPane();

        Dimension preferredSize = treeScroll.getPreferredSize();
        Dimension widePreferred = new Dimension(200, (int) preferredSize.getHeight());
        treeScroll.setPreferredSize(widePreferred);

        JPanel fileView = new JPanel(new BorderLayout(3, 3));

        detailView.add(fileView, BorderLayout.SOUTH);

        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScroll, detailView);

        JPanel simpleOutput = new JPanel(new BorderLayout(3, 3));
        progressBar = new JProgressBar();
        simpleOutput.add(progressBar, BorderLayout.EAST);
        progressBar.setVisible(false);
        showChildren(getCurrentDir().toPath());
        //table.setDragEnabled(true);
        table.setColumnSelectionAllowed(false);

        // Menu popup
        Pmenu = new JPopupMenu();
        changeProjectitem = new JMenuItem("Reassign");
        renameProjectitem = new JMenuItem("Rename");
        twitem = new JMenuItem("To workspace");
        tlitem = new JMenuItem("To local");
        processitem = new JMenuItem("Select for process");
        switch (mode) {
        case 0:
            Pmenu.add(twitem);
            twitem.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    parentFrame.getBtnlocalTowork().doClick();
                }
            });
            break;
        case 1:
            Pmenu.add(tlitem);
            Pmenu.add(processitem);
            tlitem.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    parentFrame.getBtnWorkTolocal().doClick();
                }
            });
            processitem.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent arg0) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            // Recupere les lignes selectionnees
                            int[] indices = table.getSelectedRows();
                            // On recupere les fichiers correspondants
                            ArrayList<File> files = new ArrayList<File>();
                            for (int i = 0; i < indices.length; i++) {
                                int row = table.convertRowIndexToModel(indices[i]);
                                File fi = ((FileTableModel) table.getModel()).getFile(row);
                                if (fi.isDirectory())
                                    files.add(fi);
                            }
                            ImageProcessingFrame imf = new ImageProcessingFrame(files);
                        }
                    });

                }
            });
            break;
        case 2:
            if (UserProfile.CURRENT_USER.getLevel() == 3) {
                Pmenu.add(changeProjectitem);
                Pmenu.add(renameProjectitem);
            }
            Pmenu.add(twitem);
            twitem.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    parentFrame.getBtndistToWorkspace().doClick();
                }
            });
            Pmenu.add(tlitem);
            tlitem.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    parentFrame.getBtndistToLocal().doClick();
                }
            });
            break;
        }
        changeProjectitem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                table.setEnabled(false);
                File from = ((FileTableModel) table.getModel())
                        .getFile(table.convertRowIndexToModel(table.getSelectedRows()[0]));

                ReassignProjectPanel reas = new ReassignProjectPanel(from.toPath()); // mode creation de liens
                Popup popup = PopupFactory.getSharedInstance().getPopup(WindowManager.MAINWINDOW, reas,
                        (int) WindowManager.MAINWINDOW.getX() + 200, (int) WindowManager.MAINWINDOW.getY() + 150);
                reas.setPopupWindow(popup);
                popup.show();
                table.setEnabled(true);
            }
        });
        renameProjectitem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                table.setEnabled(false);
                final File from = ((FileTableModel) table.getModel())
                        .getFile(table.convertRowIndexToModel(table.getSelectedRows()[0]));
                JDialog.setDefaultLookAndFeelDecorated(true);
                String s = (String) JOptionPane.showInputDialog(WindowManager.MAINWINDOW, "New project name ?",
                        "Rename project", JOptionPane.PLAIN_MESSAGE, null, null, from.getName());

                //If a string was returned, say so.
                if ((s != null) && (s.length() > 0)) {
                    ProjectDAO pdao = new MySQLProjectDAO();
                    if (new File(from.getParent() + File.separator + s).exists()) {
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                JDialog.setDefaultLookAndFeelDecorated(true);
                                JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                        "Couldn't rename " + from.getName()
                                                + " (A file with this filename already exists)",
                                        "Renaming error", JOptionPane.ERROR_MESSAGE);
                            }
                        });
                        WindowManager.mwLogger.log(Level.SEVERE,
                                "Error during file project renaming (" + from.getName() + "). [Duplication error]");
                    } else {
                        try {
                            boolean succeed = pdao.renameProject(from.getName(), s);
                            if (!succeed) {
                                SwingUtilities.invokeLater(new Runnable() {

                                    @Override
                                    public void run() {
                                        JDialog.setDefaultLookAndFeelDecorated(true);
                                        JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                                "Couldn't rename " + from.getName()
                                                        + " (no project with this name)",
                                                "Renaming error", JOptionPane.ERROR_MESSAGE);
                                    }
                                });
                            } else {
                                from.renameTo(new File(from.getParent() + File.separator + s));
                                // on renomme le repertoire nifti ou dicom correspondant si il existe
                                switch (from.getParentFile().getName()) {
                                case ServerInfo.NRI_ANALYSE_NAME:
                                    if (new File(from.getAbsolutePath().replaceAll(ServerInfo.NRI_ANALYSE_NAME,
                                            ServerInfo.NRI_DICOM_NAME)).exists())
                                        try {
                                            Files.move(Paths.get(from.getAbsolutePath().replaceAll(
                                                    ServerInfo.NRI_ANALYSE_NAME, ServerInfo.NRI_DICOM_NAME)),
                                                    Paths.get(from.getParent().replaceAll(
                                                            ServerInfo.NRI_ANALYSE_NAME, ServerInfo.NRI_DICOM_NAME)
                                                            + File.separator + s));
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                            SwingUtilities.invokeLater(new Runnable() {

                                                @Override
                                                public void run() {
                                                    JDialog.setDefaultLookAndFeelDecorated(true);
                                                    JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                                            "Couldn't rename " + from.getName()
                                                                    + " (error with file system)",
                                                            "Renaming error", JOptionPane.ERROR_MESSAGE);
                                                }
                                            });
                                            WindowManager.mwLogger.log(Level.SEVERE,
                                                    "Error during file project renaming (" + from.getName() + ")",
                                                    e);
                                        } //from.renameTo(new File(from.getParent().replaceAll(ServerInfo.NRI_ANALYSE_NAME, ServerInfo.NRI_DICOM_NAME)+File.separator+s));
                                    break;
                                case ServerInfo.NRI_DICOM_NAME:
                                    if (new File(from.getAbsolutePath().replaceAll(ServerInfo.NRI_DICOM_NAME,
                                            ServerInfo.NRI_ANALYSE_NAME)).exists())
                                        try {
                                            Files.move(Paths.get(from.getAbsolutePath().replaceAll(
                                                    ServerInfo.NRI_DICOM_NAME, ServerInfo.NRI_ANALYSE_NAME)),
                                                    Paths.get(from.getParent().replaceAll(ServerInfo.NRI_DICOM_NAME,
                                                            ServerInfo.NRI_ANALYSE_NAME) + File.separator + s));
                                        } catch (IOException e) {
                                            SwingUtilities.invokeLater(new Runnable() {

                                                @Override
                                                public void run() {
                                                    JDialog.setDefaultLookAndFeelDecorated(true);
                                                    JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                                            "Couldn't rename " + from.getName()
                                                                    + " (error with file system)",
                                                            "Renaming error", JOptionPane.ERROR_MESSAGE);
                                                }
                                            });
                                            e.printStackTrace();
                                            WindowManager.mwLogger.log(Level.SEVERE,
                                                    "Error during file project renaming (" + from.getName() + ")",
                                                    e);
                                        } //from.renameTo(new File(from.getParent().replaceAll(ServerInfo.NRI_DICOM_NAME, ServerInfo.NRI_ANALYSE_NAME)+File.separator+s));
                                    break;
                                }
                                refresh();
                            }
                        } catch (final SQLException e) {
                            WindowManager.mwLogger.log(Level.SEVERE, "Error during SQL project renaming", e);
                            SwingUtilities.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    JDialog.setDefaultLookAndFeelDecorated(true);
                                    JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                            "Exception : " + e.toString(), "Openning error",
                                            JOptionPane.ERROR_MESSAGE);
                                }
                            });
                        }
                    }
                }
                table.setEnabled(true);
            }
        });
        table.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent me) {

            }

            public void mouseEntered(MouseEvent e) {
            }

            public void mouseExited(MouseEvent e) {
            }

            public void mousePressed(MouseEvent e) {
            }

            public void mouseReleased(MouseEvent me) {
                if (me.getButton() == 3 && table.getSelectedRowCount() > 0) {
                    int row = table.convertRowIndexToModel(table.rowAtPoint(me.getPoint()));
                    changeProjectitem.setVisible(isPatient(((FileTableModel) table.getModel()).getFile(row)));
                    renameProjectitem.setVisible(isProject(((FileTableModel) table.getModel()).getFile(row)));
                    Pmenu.show(me.getComponent(), me.getX(), me.getY());
                }
            }
        });
        //

        //}
        return tableScroll;
    }

    public boolean isPatient(File fi) {
        String[] parts = fi.getAbsolutePath().split(Pattern.quote(File.separator));
        int serverdirlen = (SystemSettings.SERVER_INFO.getServerDir().toString()
                .split(Pattern.quote(File.separator))).length + 1;// +1 pour NRI-ANALYSE et NRI-DICOM
        if (parts.length == (serverdirlen))
            return false;
        if (!fi.getName().contains("..")) {
            int count = 0;
            for (int i = serverdirlen; i < parts.length; i++) {
                if (!parts[i].isEmpty()) {
                    count++;
                }
            }
            return count == 2;
        }
        return false;
    }

    public boolean isProject(File fi) {
        String[] parts = fi.getAbsolutePath().split(Pattern.quote(File.separator));
        int serverdirlen = (SystemSettings.SERVER_INFO.getServerDir().toString()
                .split(Pattern.quote(File.separator))).length + 1;// +1 pour NRI-ANALYSE et NRI-DICOM
        if (parts.length == (serverdirlen))
            return false;
        if (!fi.getName().contains("..")) {
            int count = 0;
            for (int i = serverdirlen; i < parts.length; i++) {
                if (!parts[i].isEmpty()) {
                    count++;
                }
            }
            return count == 1;
        }
        return false;
    }

    /**
      * Rentre dans un repertoire
      * @param row
      * @param column
      */
    protected void mouseDblClicked(int row, int column) {
        final File file = ((FileTableModel) table.getModel()).getFile(row);
        if (file.isDirectory()) {
            try {
                setCurrentDir(file.getCanonicalFile());
                showChildren(Paths.get(file.getCanonicalPath()));
            } catch (IOException e) {
                WindowManager.mwLogger.log(Level.WARNING, "FileManager mouseDblClicked error.", e);
            }
        } else {
            // si on est dans la vue admin et qu'on clic sur un nifti encrypte
            if (file.getName().endsWith(".nii" + AESCrypt.ENCRYPTSUFFIX) && mode == 2) {
                WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(true);
                Thread tr = new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            copySelectedFilesAndDecryptTo(SystemSettings.SERVER_INFO.getTempDir().toFile());
                            File copiedFile = new File(SystemSettings.SERVER_INFO.getTempDir() + File.separator
                                    + file.getName().substring(0, file.getName().length() - 4));
                            WindowManager.MAINWINDOW.getViewerPanel().open(copiedFile.toPath());
                            WindowManager.MAINWINDOW.getOngletPane()
                                    .setSelectedComponent(WindowManager.MAINWINDOW.getViewerPanel());
                            copiedFile.deleteOnExit();
                            WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(false);
                        } catch (final Exception e) {
                            SwingUtilities.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                            "Exception : " + e.toString(), "Openning error",
                                            JOptionPane.ERROR_MESSAGE);
                                }
                            });
                            WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(false);
                            WindowManager.mwLogger.log(Level.WARNING, "FileManager Openning error.", e);
                        }
                    }
                });
                tr.start();
            } else {
                // si c'est un nifti non crypte
                if (file.getName().endsWith(".nii") || file.getName().endsWith(".img")
                        || file.getName().endsWith(".nii.gz") || file.getName().endsWith(".hdr")) {
                    WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(true);
                    WindowManager.MAINWINDOW.getOngletPane()
                            .setSelectedComponent(WindowManager.MAINWINDOW.getViewerPanel());
                    Thread tr = new Thread(new Runnable() {

                        @Override
                        public void run() {
                            try {
                                WindowManager.MAINWINDOW.getViewerPanel().open(file.toPath());
                                WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(false);
                            } catch (final Exception e) {
                                SwingUtilities.invokeLater(new Runnable() {

                                    @Override
                                    public void run() {
                                        JOptionPane.showMessageDialog(WindowManager.MAINWINDOW,
                                                "Exception : " + e.toString(), "Openning error",
                                                JOptionPane.ERROR_MESSAGE);
                                    }
                                });
                                WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(false);
                                WindowManager.mwLogger.log(Level.WARNING, "FileManager Openning error.", e);
                            }
                        }
                    });
                    tr.start();
                } else {
                    try {
                        desktop.open(file);
                    } catch (Throwable t) {
                        showThrowable(t);
                        WindowManager.mwLogger.log(Level.WARNING, "FileManager Openning error.", t);
                    }
                }
            }
        }
    }

    /**
     * Change le repertoire actuel du filemanager
     * @param dir
     */
    public void switchToDir(Path dir) {
        try {
            setCurrentDir(dir.toFile().getCanonicalFile());
            showChildren(dir);
        } catch (IOException e) {
            WindowManager.mwLogger.log(Level.WARNING, "FileManager switchToDir error.", e);
        }
    }

    /**
     * Deplace les fichiers / repertoire selectionnees vers le dossier dir
     * @param currentDir2
     * @throws IOException 
     */
    public void copySelectedFilesTo(File dir) throws IOException {
        // Recupere les lignes selectionnees
        int[] indices = table.getSelectedRows();
        // On recupere les fichiers correspondants
        ArrayList<File> files = new ArrayList<File>();
        for (int i = 0; i < indices.length; i++) {
            int row = table.convertRowIndexToModel(indices[i]);
            File fi = ((FileTableModel) table.getModel()).getFile(row);
            if (!continueAction) {
                continueAction = true;
                return;
            }
            if (!fi.getName().contains("..")) {
                if (fi.isDirectory())
                    FileUtils.copyDirectoryToDirectory(fi, dir);
                else
                    FileUtils.copyFileToDirectory(fi, dir);
            }
        }
    }

    /**
      * Supprime les fichiers / repertoire selectionnees vers 
      * @throws IOException 
      */
    public void deleteSelectedFiles() throws IOException {
        // Recupere les lignes selectionnees
        int[] indices = table.getSelectedRows();
        // On recupere les fichiers correspondants
        ArrayList<File> files = new ArrayList<File>();
        for (int i = 0; i < indices.length; i++) {
            int row = table.convertRowIndexToModel(indices[i]);
            File fi = ((FileTableModel) table.getModel()).getFile(row);
            if (!continueAction) {
                continueAction = true;
                return;
            }
            if (!fi.getName().contains("..")) {
                if (fi.isDirectory())
                    FileUtils.deleteQuietly(fi);
                else
                    fi.delete();
            }
        }
    }

    /**
      * Supprime les fichiers / repertoire sur le serveur
     * @throws Exception 
      */
    public void deleteServerFile(int row) throws Exception {
        File fi = ((FileTableModel) table.getModel()).getFile(row);
        WindowManager.mwLogger.log(Level.INFO, "Deleting " + fi.getAbsolutePath());
        deleServerFile(fi);
    }

    /**
      * Supprime les fichiers / repertoire sur le serveur
     * @throws Exception 
      */
    public void deleServerFile(File fi) throws Exception {
        String[] parts = fi.getAbsolutePath().split(Pattern.quote(File.separator));
        int serverdirlen = (SystemSettings.SERVER_INFO.getServerDir().toString()
                .split(Pattern.quote(File.separator))).length + 1;// +1 pour NRI-ANALYSE et NRI-DICOM
        if (parts.length == (serverdirlen))
            return;
        if (!fi.getName().contains("..")) {
            if (!fi.canWrite() && fi.exists()) {
                throw new Exception("Can't delete " + fi.getAbsolutePath());
            }
            // on met a jours la bdd
            int count = 0;
            for (int i = serverdirlen; i < parts.length; i++) {
                if (!parts[i].isEmpty()) {
                    count++;
                } else {
                    throw new Exception("Error with file path structure.");
                }
            }
            String project = null;
            String patient = null;
            String acqdate = null;
            String protocol = null;
            String serie = null;
            String image = null;
            if (parts[serverdirlen - 1].equals(ServerInfo.NRI_DICOM_NAME)) {
                switch (count) {
                case 1:// on delete un projet complet
                    project = parts[serverdirlen];
                    ProjectDAO pdao = new MySQLProjectDAO();
                    pdao.removeProject(project);
                    break;
                case 2: // delete d'un patient
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    PatientDAO patdao = new MySQLPatientDAO();
                    patdao.removePatient(project, patient);
                    break;
                case 3://acqdate
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    AcquisitionDateDAO adao = new MySQLAcquisitionDateDAO();
                    adao.removeAcqdate(project, patient, acqdate);
                    break;
                case 4://protocol
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    ProtocolDAO prdao = new MySQLProtocolDAO();
                    prdao.removeProtocol(project, patient, acqdate, protocol);
                    break;
                case 5://serie
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    serie = parts[serverdirlen + 4];
                    SerieDAO sdao = new MySQLSerieDAO();
                    sdao.removeSerie(project, patient, acqdate, protocol, serie);
                    break;
                case 6://Image
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    serie = parts[serverdirlen + 4];
                    image = parts[serverdirlen + 5];
                    image = image.substring(0, image.length() - AESCrypt.ENCRYPTSUFFIX.length());//-4
                    switch (parts[serverdirlen - 1]) {//NRI-ANALYZE ou DICOM
                    case ServerInfo.NRI_DICOM_NAME:
                        DicomImageDAO ddao = new MySQLDicomImageDAO();
                        ddao.removeDicom(project, patient, acqdate, protocol, serie, image);
                        break;
                    case ServerInfo.NRI_ANALYSE_NAME:
                        NiftiImageDAO ndao = new MySQLNiftiImageDAO();
                        ndao.removeNifti(project, patient, acqdate, protocol, serie, image);
                        break;
                    }

                    break;
                }
            } else {
                // dans le cas des nifti on delete que les images de la bdd 
                NiftiImageDAO ndao = new MySQLNiftiImageDAO();
                switch (count) {
                case 1:// on delete un projet complet
                    project = parts[serverdirlen];
                    ndao.removeNiftisForProject(project);
                    break;
                case 2: // delete d'un patient
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    ndao.removeNiftisForPatient(project, patient);
                    break;
                case 3://acqdate
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    ndao.removeNiftisForAcqDate(project, patient, acqdate);
                    break;
                case 4://protocol
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    ndao.removeNiftisForProtocol(project, patient, acqdate, protocol);
                    break;
                case 5://serie
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    serie = parts[serverdirlen + 4];
                    ndao.removeNiftisForSerie(project, patient, acqdate, protocol, serie);
                    break;
                case 6://Image
                    project = parts[serverdirlen];
                    patient = parts[serverdirlen + 1];
                    acqdate = parts[serverdirlen + 2];
                    protocol = parts[serverdirlen + 3];
                    serie = parts[serverdirlen + 4];
                    image = parts[serverdirlen + 5];
                    image = image.substring(0, image.length() - AESCrypt.ENCRYPTSUFFIX.length());//-4
                    ndao.removeNifti(project, patient, acqdate, protocol, serie, image);

                    break;
                }
            }
            // on supprime d'abord les fichiers (au moins si ca plante on aura pas de decalage bdd
            if (fi.isDirectory()) {
                if (!fi.canWrite() && fi.exists()) {
                    throw new Exception("Can't delete " + fi.getAbsolutePath());
                }
                FileUtils.deleteQuietly(fi);
                // on supprime l'equivalent dans l'autre repertoire (DICOM ou NIFTI) enfin sauf si on supprime que nifti !
                switch (parts[serverdirlen - 1]) {//NRI-ANALYZE ou DICOM
                case ServerInfo.NRI_DICOM_NAME:
                    parts[serverdirlen - 1] = ServerInfo.NRI_ANALYSE_NAME;
                    String opath = "";
                    for (String p : parts)
                        opath += p + File.separator;
                    // on enleve le dernier separator 
                    opath = opath.substring(0, opath.length() - 1);
                    File temp = new File(opath);
                    if (temp.exists())
                        FileUtils.deleteQuietly(new File(opath));
                    break;
                case ServerInfo.NRI_ANALYSE_NAME:
                    // on delete en cascade les parent si ils deviennent vide
                    boolean continu = true;
                    File parent = fi.getParentFile();
                    do {
                        if (getLocationOfFile(parent) > 1) {
                            if (parent.isDirectory() && parent.list().length == 0) {
                                FileUtils.deleteQuietly(parent);
                                parent = parent.getParentFile();
                            } else {
                                continu = false;
                            }
                        } else {
                            continu = false;
                        }
                    } while (continu);
                    // Pourquoi supprimer dicom si on demande juste la supression du nifti ?
                    // on peut tres bien vouloir forcer une nouvelle conversion nifti
                    //parts[serverdirlen-1] = ServerInfo.NRI_DICOM_NAME;
                    break;
                }

            } else {
                fi.delete();
                if (parts[serverdirlen - 1].equals(ServerInfo.NRI_ANALYSE_NAME)) {
                    // si c'est un nifti on supprime aussi les fichiers associes
                    try {
                        // on verifie si il n'y a pas des fichiers associe a supprimer (fichiers texte genre bval)
                        String path = fi.getParent();
                        String rootname = fi.getName();
                        if (rootname.endsWith(AESCrypt.ENCRYPTSUFFIX)) {
                            rootname = fi.getName().substring(0, fi.getName().lastIndexOf("."));//sans le .enc
                            rootname = rootname.substring(0, rootname.lastIndexOf("."));//sans le .nii
                        } else {
                            rootname = fi.getName().substring(0, fi.getName().lastIndexOf(".") - 1);
                        }
                        // on essai de supprimer les fichiers si ils existent
                        for (String suf : NiftiDaemon.suffixeToRemoveWithNifti) {
                            if (new File(path + File.separator + rootname + suf).exists())
                                new File(path + File.separator + rootname + suf).delete();
                            else if (new File(path + File.separator + rootname + suf + AESCrypt.ENCRYPTSUFFIX)
                                    .exists())
                                new File(path + File.separator + rootname + suf + AESCrypt.ENCRYPTSUFFIX).delete();
                        }
                    } catch (Exception e) {
                    }
                }
            }
        }
        // on vide le cache pour eviter des erreurs issue de decalage db // cache
        SystemSettings.SERVER_INFO.getDbCache().clear();
    }

    /**
      * Deplace les fichiers / repertoire selectionnees vers le dossier dir
      * et decrypte
      * @param currentDir2
      * @throws IOException 
      */
    public void copySelectedFilesAndDecryptTo(File dir) throws IOException {
        if (!SystemSettings.DECRYPT_DAEMON.isAlive()) {
            SystemSettings.DECRYPT_DAEMON = new DecryptDaemon();
            SystemSettings.DECRYPT_DAEMON.start();
        }
        // Recupere les lignes selectionnees
        int[] indices = table.getSelectedRows();
        // On recupere les fichiers correspondants
        ArrayList<File> files = new ArrayList<File>();
        for (int i = 0; i < indices.length; i++) {
            int row = table.convertRowIndexToModel(indices[i]);
            File fi = ((FileTableModel) table.getModel()).getFile(row);
            if (!continueAction) {
                continueAction = true;
                return;
            }
            if (!fi.getName().contains("..")) {
                copyAndDecrypt(fi, dir);
            }
        }
        while (!SystemSettings.DECRYPT_DAEMON.isWaiting() && continueAction) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        continueAction = true;
        SystemSettings.DECRYPT_DAEMON.cleanList();
    }

    /**
     * Recursive copie & decrypt
     * @param fi
     * @param dir
     * @param level le niveau de recursivite dans lequel on se trouve (0)
     */
    public static void copyAndDecrypt(File fi, File dir, int level) {
        if (stopAction) {
            if (level == 0)
                stopAction = false;
            return;
        }
        if (fi.isDirectory()) {
            File ndir = new File(dir.getAbsolutePath() + File.separator + fi.getName());
            ndir.mkdirs();
            for (File cf : fi.listFiles()) {
                if (!cf.getName().contains("..") && !cf.getName().equals(".")) {
                    copyAndDecrypt(cf, ndir, level + 1);
                }
                if (stopAction) {
                    if (level == 0)
                        stopAction = false;
                    return;
                }
            }
        } else {
            SystemSettings.DECRYPT_DAEMON.addFileToDecrypt(fi.toPath(), dir.toPath());
        }
    }

    /**
     * On definit le niveau 0 de recursivite par defaut
     * @param fi
     * @param dir
     */
    public static void copyAndDecrypt(File fi, File dir) {
        copyAndDecrypt(fi, dir, 0);
    }

    /**
     * Stoppe l'action que realise ce filetree (copie de fichier // decryptage etc)
     */
    public void terminateAction() {
        continueAction = false;
    }

    public void terminateCopyAndDecrypt() {
        SystemSettings.DECRYPT_DAEMON.cleanList();
    }

    private void showThrowable(Throwable t) {
        t.printStackTrace();
        JOptionPane.showMessageDialog(parentFrame, t.toString(), t.getMessage(), JOptionPane.ERROR_MESSAGE);
        parentFrame.repaint();
    }

    /** Update the table on the EDT */
    private void setTableData(final File[] files) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (fileTableModel == null) {
                    fileTableModel = new FileTableModel(table);
                    table.setModel(fileTableModel);
                }
                table.getSelectionModel().removeListSelectionListener(listSelectionListener);
                fileTableModel.setFiles(files);
                table.getSelectionModel().addListSelectionListener(listSelectionListener);
                if (!cellSizesSet && files != null && files.length > 0) {
                    Icon icon = fileSystemView.getSystemIcon(files[0]);

                    // size adjustment to better account for icons
                    table.setRowHeight(icon.getIconHeight() + rowIconPadding);

                    setColumnWidth(0, -1);
                    //  setColumnWidth(3,70);
                    //  table.getColumnModel().getColumn(3).setMaxWidth(60);

                    cellSizesSet = true;
                }
            }
        });
    }

    private void setColumnWidth(int column, int width) {
        TableColumn tableColumn = table.getColumnModel().getColumn(column);
        if (width < 0) {
            // use the preferred width of the header..
            JLabel label = new JLabel((String) tableColumn.getHeaderValue());
            Dimension preferred = label.getPreferredSize();
            // altered 10->14 as per camickr comment.
            width = (int) preferred.getWidth() + 14;
        }
        tableColumn.setPreferredWidth(width);
        tableColumn.setMaxWidth(width);
        tableColumn.setMinWidth(width);
    }

    /** Add the files that are contained within the directory of this node.
    Thanks to Hovercraft Full Of Eels. */
    private void showChildren(final Path node) {
        //tree.setEnabled(false);

        SwingWorker<Void, File> worker = new SwingWorker<Void, File>() {
            @Override
            public Void doInBackground() {
                table.setEnabled(false);
                File file = (File) node.toFile();
                setCurrentDir(file);
                if (file.isDirectory()) {
                    File[] files = fileSystemView.getFiles(file, !UserProfile.SHOW_HIDDEN_FILES); //!!
                    File[] filesTemp = new File[files.length + 1];
                    File[] filesWithParent;
                    filesTemp[0] = new File(file.getAbsolutePath() + "/..");
                    for (int i = 1; i < filesTemp.length; i++) {
                        filesTemp[i] = files[i - 1];
                    }
                    switch (getMode()) {
                    case 1:
                        List<File> list = new ArrayList<File>();
                        if (file.toPath().equals(SystemSettings.SERVER_INFO.getServerDir())) {
                            for (File fi : filesTemp) {
                                for (Project p : UserProfile.CURRENT_USER.getProjects()) {
                                    if ((ServerInfo.WORKSPACE_PREFIXE + p.getNom()).equals(fi.getName())) {
                                        list.add(fi);
                                    }
                                }
                            }
                            filesWithParent = list.toArray(new File[list.size()]);
                        } else {
                            filesWithParent = filesTemp;
                        }

                        break;
                    case 2:
                        List<File> list2 = new ArrayList<File>();
                        if (file.toPath().equals(SystemSettings.SERVER_INFO.getServerDir())) {
                            for (File fi : filesTemp) {
                                if (fi.getName().equals(ServerInfo.NRI_DICOM_NAME)
                                        || fi.getName().equals(ServerInfo.NRI_ANALYSE_NAME)) {
                                    list2.add(fi);
                                }
                            }
                            filesWithParent = list2.toArray(new File[list2.size()]);
                        } else {
                            filesWithParent = filesTemp;
                        }
                        break;
                    default:
                        filesWithParent = filesTemp;
                    }
                    if (filesWithParent != null) {
                        setTableData(filesWithParent);
                    }
                }
                return null;
            }
        };
        worker.execute();
    }

    public File getCurrentDir() {
        return currentDir;
    }

    public void setCurrentDir(File currentDir) {
        this.currentDir = currentDir;
    }

    public static boolean copyFile(File from, File to) throws IOException {

        boolean created = to.createNewFile();

        if (created) {
            FileChannel fromChannel = null;
            FileChannel toChannel = null;
            try {
                fromChannel = new FileInputStream(from).getChannel();
                toChannel = new FileOutputStream(to).getChannel();

                toChannel.transferFrom(fromChannel, 0, fromChannel.size());

                // set the flags of the to the same as the from
                to.setReadable(from.canRead());
                to.setWritable(from.canWrite());
                to.setExecutable(from.canExecute());
            } finally {
                if (fromChannel != null) {
                    fromChannel.close();
                }
                if (toChannel != null) {
                    toChannel.close();
                }
                return false;
            }
        }
        return created;
    }

    /**
     * Renvoi le code du type de repertoire dans lequel on se trouve dans le serveur (patient, acqdate etc)
     * @param fi
     * @return
     */
    public int getLocationOfFile(File fi) {
        if (!fi.getAbsolutePath().startsWith(SystemSettings.SERVER_INFO.getServerDir().toString()))
            return -1;
        String[] parts = fi.getAbsolutePath().split(Pattern.quote(File.separator));
        int serverdirlen = (SystemSettings.SERVER_INFO.getServerDir().toString()
                .split(Pattern.quote(File.separator))).length + 1;// +1 pour NRI-ANALYSE et NRI-DICOM
        if (parts.length == (serverdirlen))
            return -1;
        if (!fi.getName().contains("..")) {
            if (!fi.canWrite()) {
                return -1;
            }
            // on met a jours la bdd
            int count = 0;
            for (int i = serverdirlen; i < parts.length; i++) {
                if (!parts[i].isEmpty()) {
                    count++;
                } else {
                    return -1;
                }
            }
            return count;
        }
        return -1;
    }

    public void refresh() {
        table.setEnabled(false);
        showChildren(currentDir.toPath());
        table.setEnabled(true);
    }

    public DefaultTreeModel getTreeModel() {
        return treeModel;
    }

    public void setTreeModel(DefaultTreeModel treeModel) {
        this.treeModel = treeModel;
    }

    public int getMode() {
        return mode;
    }

    public void setMode(int mode) {
        this.mode = mode;
    }

    public JTable getTable() {
        return table;
    }

    public void setTable(JTable table) {
        this.table = table;
    }

    public FileTableModel getFileTableModel() {
        return fileTableModel;
    }

    public void setFileTableModel(FileTableModel fileTableModel) {
        this.fileTableModel = fileTableModel;
    }

    /**
     * Coupe une action realise statiquement (copyAndDecrypt)
     */
    public static void stopAction() {
        stopAction = true;
    }

    public static void setStopAction(boolean b) {
        stopAction = b;
    }

}

/** A TableModel to hold File[]. */
class FileTableModel extends AbstractTableModel {

    private JTable parent;
    private File[] files;
    private Object[] size;// on stock en cache les infos pour eviter les overhead
    private Object[] lastMod;
    private FileSystemView fileSystemView = FileSystemView.getFileSystemView();
    private String[] columns = { "Icon", "File", "Size", "Last Modified", };

    FileTableModel(JTable parent) {
        this(new File[0]);
        this.parent = parent;
    }

    FileTableModel(File[] files) {
        this.files = files;
    }

    // Attention beaucoup d'overhead
    public Object getValueAt(int row, int column) {
        if (row >= files.length)
            return null;
        File file = files[row];
        switch (column) {
        case 0:
            return fileSystemView.getSystemIcon(file);
        case 1:
            return fileSystemView.getSystemDisplayName(file);
        case 2:
            return size[row];
        /*long nbytes = file.length();
        long kilobytes = (nbytes / 1024);
        long megabytes = (kilobytes / 1024);
        long gigabytes = (megabytes / 1024);
        if(kilobytes>1 && megabytes<1)
           return kilobytes + " Kb";
        else if(megabytes>=1 && gigabytes<1)
           return megabytes + " Mb";
        else if(gigabytes>=1)
           return gigabytes + " Gb";
         return nbytes + " b";*/
        case 3:
            return lastMod[row];
        //return file.lastModified();
        default:
            System.err.println("Logic Error");
        }
        return "";
    }

    public int getColumnCount() {
        return columns.length;
    }

    public Class<?> getColumnClass(int column) {
        switch (column) {
        case 0:
            return ImageIcon.class;
        case 2:
            return Long.class;
        case 3:
            return Date.class;
        }
        return String.class;
    }

    public String getColumnName(int column) {
        return columns[column];
    }

    public int getRowCount() {
        return files.length;
    }

    public File getFile(int row) {
        return files[row];
    }

    public void setFiles(final File[] filesu) {
        WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(true);
        Thread tr = new Thread(new Runnable() {

            @Override
            public void run() {
                files = filesu;
                updateSize();
                updateLastMod();
                WindowManager.MAINWINDOW.getProgressBarPanel().setVisible(false);
                SwingUtilities.invokeLater(new Runnable() {

                    @Override
                    public void run() {
                        fireTableDataChanged();
                    }
                });
                parent.setEnabled(true);
            }
        });
        tr.start();

    }

    /**
     * Met a jours le cache pour les date de modification des fichiers
     * (empeche l'overhead)
     */
    private void updateLastMod() {
        lastMod = new Object[files.length];
        for (int i = 0; i < files.length; i++) {
            lastMod[i] = files[i].lastModified();
        }
    }

    /**
     * Met a jours les informations sur les tailles de fichiers
     */
    private void updateSize() {
        size = new Object[files.length];
        for (int i = 0; i < files.length; i++) {
            long nbytes = files[i].length();
            long kilobytes = (nbytes / 1024);
            long megabytes = (kilobytes / 1024);
            long gigabytes = (megabytes / 1024);
            if (kilobytes > 1 && megabytes < 1)
                size[i] = kilobytes + " Kb";
            else if (megabytes >= 1 && gigabytes < 1)
                size[i] = megabytes + " Mb";
            else if (gigabytes >= 1)
                size[i] = gigabytes + " Gb";
            else
                size[i] = nbytes + " b";
        }
    }
}

/** A TreeCellRenderer for a File. */
class FileTreeCellRenderer extends DefaultTreeCellRenderer {

    private FileSystemView fileSystemView;

    private JLabel label;

    FileTreeCellRenderer() {
        label = new JLabel();
        label.setOpaque(true);
        fileSystemView = FileSystemView.getFileSystemView();
    }

    @Override
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded,
            boolean leaf, int row, boolean hasFocus) {

        DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
        File file = (File) node.getUserObject();
        label.setIcon(fileSystemView.getSystemIcon(file));
        label.setText(fileSystemView.getSystemDisplayName(file));
        label.setToolTipText(file.getPath());

        if (selected) {
            label.setBackground(backgroundSelectionColor);
            label.setForeground(textSelectionColor);
        } else {
            label.setBackground(backgroundNonSelectionColor);
            label.setForeground(textNonSelectionColor);
        }

        return label;
    }
}