Author: jflesch
Date: 2007-01-25 07:03:17 +0000 (Thu, 25 Jan 2007)
New Revision: 11613

Added:
   trunk/apps/Thaw/images/database.png
   trunk/apps/Thaw/src/thaw/plugins/index/IndexFolder.java
Removed:
   trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java
Modified:
   trunk/apps/Thaw/src/thaw/core/FreenetURIHelper.java
   trunk/apps/Thaw/src/thaw/core/IconBox.java
   trunk/apps/Thaw/src/thaw/core/Logger.java
   trunk/apps/Thaw/src/thaw/core/MainWindow.java
   trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
   trunk/apps/Thaw/src/thaw/core/PluginManager.java
   trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
   trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java
   trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
   trunk/apps/Thaw/src/thaw/gui/JDragTree.java
   trunk/apps/Thaw/src/thaw/i18n/thaw.properties
   trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
   trunk/apps/Thaw/src/thaw/plugins/Hsqldb.java
   trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java
   trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java
   trunk/apps/Thaw/src/thaw/plugins/index/AutoRefresh.java
   trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java
   trunk/apps/Thaw/src/thaw/plugins/index/File.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileList.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileManagementHelper.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java
   trunk/apps/Thaw/src/thaw/plugins/index/Index.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexConfigPanel.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexProgressBar.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexRoot.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java
   trunk/apps/Thaw/src/thaw/plugins/index/Link.java
   trunk/apps/Thaw/src/thaw/plugins/index/LinkList.java
   trunk/apps/Thaw/src/thaw/plugins/index/LinkManagementHelper.java
   trunk/apps/Thaw/src/thaw/plugins/index/LinkTable.java
   trunk/apps/Thaw/src/thaw/plugins/index/SearchBar.java
   trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java
   trunk/apps/Thaw/src/thaw/plugins/index/Tables.java
   trunk/apps/Thaw/src/thaw/plugins/index/UnknownIndexList.java
   trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java
   trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java
Log:
Rewrite of thaw/plugins/index/Index.java + thaw/plugins/index/IndexFolder.java 
(previously IndexCategory.java), and many bug fixes

Added: trunk/apps/Thaw/images/database.png
===================================================================
(Binary files differ)


Property changes on: trunk/apps/Thaw/images/database.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: trunk/apps/Thaw/src/thaw/core/FreenetURIHelper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/FreenetURIHelper.java 2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/core/FreenetURIHelper.java 2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -1,6 +1,8 @@
 package thaw.core;

-
+/**
+ * would be better called "FreenetKeyHelper" ... but too late :p
+ */
 public class FreenetURIHelper {

        public FreenetURIHelper() {
@@ -217,10 +219,18 @@
                if (split.length < 3)
                        return -1;

-               return Integer.parseInt(split[2]);
+               try {
+                       return Integer.parseInt(split[2]);
+               } catch(NumberFormatException e) {
+                       Logger.error(new FreenetURIHelper(), "Unable to parse 
'"+key +"'");
+                       return -1;
+               }
        }


+       /**
+        * will lower the case !
+        */
        public static String getComparablePart(String key) {
                if (key == null)
                        return null;
@@ -231,7 +241,7 @@
                int maxLength = 0;

                if (key.length() <= 70)
-                       maxLength = key.length();
+                       return key.toLowerCase();
                else
                        maxLength = 70;


Modified: trunk/apps/Thaw/src/thaw/core/IconBox.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/IconBox.java  2007-01-25 03:40:46 UTC (rev 
11612)
+++ trunk/apps/Thaw/src/thaw/core/IconBox.java  2007-01-25 07:03:17 UTC (rev 
11613)
@@ -76,6 +76,7 @@
        public static ImageIcon minImportAction;
        public static ImageIcon minExportAction;

+       public static ImageIcon database;

        /**
         * Not really used
@@ -154,6 +155,7 @@
                IconBox.importExport = IconBox.loadIcon("refresh.png");
                IconBox.minImportAction = IconBox.loadIcon("min-import.png");
                IconBox.minExportAction = IconBox.loadIcon("min-export.png");
+               IconBox.database = IconBox.loadIcon("database.png");
        }

 }

Modified: trunk/apps/Thaw/src/thaw/core/Logger.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Logger.java   2007-01-25 03:40:46 UTC (rev 
11612)
+++ trunk/apps/Thaw/src/thaw/core/Logger.java   2007-01-25 07:03:17 UTC (rev 
11613)
@@ -16,11 +16,11 @@
         * 3 = Errors + warnings + notices + infos
         * 4 = Errors + warnings + notices + infos + debug
         * 5 = [...] + horrible things that only God could understand easily.
-        *             (or maybe someone having the FCPv2 doc :)
+        *             (or maybe someone having the FCPv2 specs :)
         *
         * 2 or more is recommanded.
         */
-       public final static int LOG_LEVEL = 3;
+       public final static int LOG_LEVEL = 2;

        private static Vector logListeners = null;


Modified: trunk/apps/Thaw/src/thaw/core/MainWindow.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/MainWindow.java       2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/core/MainWindow.java       2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -510,7 +510,7 @@

        public void showDialogAbout() {
                final JLabel[] labels = new JLabel[] {
-                       new JLabel(I18n.getMessage("thaw.about.l1")),
+                       null,
                        new JLabel(I18n.getMessage("thaw.about.l2")),
                        new JLabel(I18n.getMessage("thaw.about.l3")),
                        new JLabel(I18n.getMessage("thaw.about.l4")),
@@ -521,6 +521,7 @@
                        new JLabel(I18n.getMessage("thaw.about.l8"))
                };

+               labels[0] = new JLabel("Thaw "+Main.VERSION);
                labels[0].setFont(new Font("Dialog", Font.BOLD, 30));

                JOptionPane.showMessageDialog(null, labels, 
I18n.getMessage("thaw.about.title"),

Modified: trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java  2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java  2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -19,7 +19,7 @@


        private final static String[] paramNames = {
-               I18n.getMessage("thaw.config.nodeAddress"),
+               I18n.getMessage("thaw.config.nodeAddress"), /* a check is done 
on this one, be warned */
                I18n.getMessage("thaw.config.nodePort"),
                I18n.getMessage("thaw.config.maxSimultaneousDownloads"),
                I18n.getMessage("thaw.config.maxSimultaneousInsertions"),
@@ -36,6 +36,9 @@
                "thawId"
        };

+       /**
+        * a check is done on the first value, be warned
+        */
        private final static String[] currentValues = new String[6];


@@ -122,9 +125,21 @@

        public void update(final Observable o, final Object arg) {
                if(arg == core.getConfigWindow().getOkButton()) {
-                       if (hasAValueChanged())
+                       if (hasAValueChanged()) {
                                configWindow.willNeedConnectionReset();

+                               if (sameComputer.isSelected() &&
+                                   
!paramFields[0].getText().equals(currentValues[0]) &&
+                                   
!"127.0.0.1".equals(paramFields[0].getText())) {
+
+                                       new WarningWindow(core,
+                                                         
I18n.getMessage("thaw.config.sameComputerButNotLocalhost.l0")+"\n"+
+                                                         
I18n.getMessage("thaw.config.sameComputerButNotLocalhost.l1")+"\n"+
+                                                         
I18n.getMessage("thaw.config.sameComputerButNotLocalhost.l2")+"\n\n"+
+                                                         
I18n.getMessage("thaw.config.sameComputerButNotLocalhost.l4"));
+                               }
+                       }
+
                        for(int i=0;i < NodeConfigPanel.paramNames.length;i++) {
                                
core.getConfig().setValue(NodeConfigPanel.configNames[i], 
paramFields[i].getText());
                        }

Modified: trunk/apps/Thaw/src/thaw/core/PluginManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/PluginManager.java    2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/core/PluginManager.java    2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -13,6 +13,7 @@
                "thaw.plugins.FetchPlugin",
                "thaw.plugins.InsertPlugin",
                "thaw.plugins.StatusBar",
+               "thaw.plugins.Hsqldb",
                "thaw.plugins.IndexBrowser",
                "thaw.plugins.IndexExporter"
        };
@@ -61,7 +62,7 @@
         * Load plugin from config or from default list.
         * Reload if already loaded.
         */
-       public boolean loadPlugins() {
+       public synchronized boolean loadPlugins() {
                plugins = new LinkedHashMap();

                Vector pluginNames;
@@ -95,7 +96,7 @@
        /**
         * Start plugins.
         */
-       public boolean runPlugins() {
+       public synchronized boolean runPlugins() {
                Iterator pluginIt;

                if (plugins == null || plugins.size() == 0) {
@@ -144,7 +145,7 @@
        /**
         * Stop all plugins.
         */
-       public boolean stopPlugins() {
+       public synchronized boolean stopPlugins() {
                Iterator pluginIt;

                if (plugins == null) {
@@ -178,7 +179,7 @@
        /**
         * Load a given plugin (without adding it to the config or running it).
         */
-       public Plugin loadPlugin(final String className) {
+       public synchronized Plugin loadPlugin(final String className) {
                Plugin plugin = null;

                Logger.info(this, "Loading plugin: '"+className+"'");
@@ -205,7 +206,7 @@
        /**
         * Run a given plugin.
         */
-       public boolean runPlugin(final String className) {
+       public synchronized boolean runPlugin(final String className) {
                Logger.info(this, "Starting plugin: '"+className+"'");

                try {
@@ -223,7 +224,7 @@
        /**
         * Stop a given plugin.
         */
-       public boolean stopPlugin(final String className) {
+       public synchronized boolean stopPlugin(final String className) {
                Logger.info(this, "Stopping plugin: '"+className+"'");

                try {
@@ -241,7 +242,7 @@
        /**
         * Unload a given plugin (without adding it to the config or running 
it).
         */
-       public boolean unloadPlugin(final String className) {
+       public synchronized boolean unloadPlugin(final String className) {
                try {
                        if(plugins.get(className) == null) {
                                Logger.warning(this, "unloadPlugin(): Plugin 
'"+className+"' already unloaded");

Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java      2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java      2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -106,6 +106,7 @@


        /**
+        * Entry point:
         * Only for initial queries : To resume queries, use 
FCPClientGet(FCPQueueManager, Hashmap).
         * @param destinationDir if null => temporary file
         * @param persistence 0 = Forever ; 1 = Until node reboot ; 2 = Until 
the app disconnect
@@ -298,9 +299,6 @@
                        successful = false;
                        fatal = true;

-                       setChanged();
-                       this.notifyObservers();
-
                        if((message.getValue("Fatal") != null) &&
                           message.getValue("Fatal").equals("false")) {
                                fatal = false;
@@ -313,6 +311,9 @@
                                isLockOwner= false;
                        }

+                       setChanged();
+                       notifyObservers();
+
                        queueManager.getQueryManager().deleteObserver(this);

                        return;
@@ -391,11 +392,11 @@

                                successful = true;
                                running = true;
-
-                               setChanged();
-                               this.notifyObservers();
                        }

+                       setChanged();
+                       this.notifyObservers();
+
                        return;
                }

@@ -451,6 +452,8 @@

                if(message.getMessageName().equals("PersistentGet")) {
                        Logger.debug(this, "PersistentGet !");
+                       setChanged();
+                       notifyObservers();
                        return;
                }


Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java    2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientHello.java    2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -12,6 +12,7 @@
  *       and start() returns false.
  */
 public class FCPClientHello implements FCPQuery, Observer {
+       public final static int NODEHELLO_TIMEOUT = 20; /* in seconds */

        private final static String FCP_EXPECTED_VERSION = "2.0";
        private String id;
@@ -33,7 +34,7 @@
                this.id = id;
                this.queryManager = queryManager;
        }
-       
+
        public void setID(final String id) {
                this.id = id;
        }
@@ -77,21 +78,27 @@
                        return false;
                }

-               while(!receiveAnswer) {
+
+               int count = 0;
+
+               while(!receiveAnswer && count < (NODEHELLO_TIMEOUT*2)) {
                        try {
                                Thread.sleep(500);
                        } catch(final java.lang.InterruptedException e) {
-                               /* Dodo j'ai dis ! */
+                               /* \_o< */
                        }
+                       count++;
                }

                if(nodeName != null) {
                        Logger.info(this, "Hello "+nodeName+", I'm Thaw :)");
                } else {
-                       Logger.warning(this, "Unable to connect, ID is probably 
already taken");
+                       Logger.warning(this, "Unable to connect, ID is probably 
already taken or there was a timeout");
+                       
queueManager.getQueryManager().getConnection().disconnect();
                        return false;
                }

+
                return true;
        }

@@ -116,14 +123,20 @@
                                queryManager.deleteObserver(this);

                                receiveAnswer = true;
+                               synchronized(this) {
+                                       notify();
+                               }
                        }

                        if("CloseConnectionDuplicateClientName".equals( 
answer.getMessageName() )) {
                                /* Damn ... ! */
-                               Logger.warning(this, "According to the node, 
Thaw ID is already used. Please change it in the configuration");
+                               Logger.warning(this, "According to the node, 
Thaw ID is already used. Please change it in the configuration (in advanced 
mode)");
                                queryManager.deleteObserver(this);
                                queryManager.getConnection().disconnect();
                                receiveAnswer = true;
+                               synchronized(this) {
+                                       notify();
+                               }
                        }
                }


Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java   2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java   2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -1,8 +1,10 @@
 package thaw.fcp;

+import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.Vector;

+import thaw.core.FreenetURIHelper;
 import thaw.core.Logger;

 /**
@@ -22,6 +24,9 @@
        private final Vector[] pendingQueries = new 
Vector[FCPQueueManager.PRIORITY_MIN+1];
        private Vector runningQueries;

+       private Hashtable keyTable;
+       private Hashtable filenameTable;
+
        private Thread scheduler;
        private boolean stopThread = false;

@@ -92,6 +97,9 @@

                for(int i = 0; i <= FCPQueueManager.PRIORITY_MIN ; i++)
                        pendingQueries[i] = new Vector();
+
+               keyTable = new Hashtable();
+               filenameTable = new Hashtable();
        }

        /**
@@ -117,7 +125,7 @@
        }

        /**
-        * @return < 0 if no limite
+        * @return < 0 if no limit
         */
        public int getMaxInsertions() {
                return maxInsertions;
@@ -139,6 +147,14 @@

                pendingQueries[query.getThawPriority()].add(query);

+               String fileKey = query.getFileKey();
+               String filename = query.getFilename();
+
+               if (FreenetURIHelper.isAKey(fileKey))
+                       
keyTable.put(FreenetURIHelper.getComparablePart(fileKey), query);
+
+               filenameTable.put(filename, query);
+
                setChanged();
                this.notifyObservers(query);

@@ -183,6 +199,15 @@

                runningQueries.add(query);

+               String fileKey = query.getFileKey();
+               String filename = query.getFilename();
+
+               if (FreenetURIHelper.isAKey(fileKey))
+                       
keyTable.put(FreenetURIHelper.getComparablePart(fileKey), query);
+
+               filenameTable.put(filename, query);
+
+
                setChanged();
                this.notifyObservers(query);

@@ -229,6 +254,14 @@
                for(int i = 0 ; i <= FCPQueueManager.PRIORITY_MIN ; i++)
                        pendingQueries[i].remove(query);

+               String fileKey = query.getFileKey();
+               String filename = query.getFilename();
+
+               if (FreenetURIHelper.isAKey(fileKey))
+                       
keyTable.remove(FreenetURIHelper.getComparablePart(fileKey));
+
+               filenameTable.remove(filename);
+
                setChanged();
                this.notifyObservers(query);
        }
@@ -279,118 +312,25 @@


        /**
-        * Not very reliable ?
+        * @param key file key or file name if key is unknown
         */
        public FCPTransferQuery getTransfer(final String key) {
-               boolean interrupted=true;
-               boolean isAKey = true;
-               Iterator it;
+               FCPTransferQuery q;

-               if (key == null)
-                       return null;
+               if (FreenetURIHelper.isAKey(key)) {
+                       q = 
(FCPTransferQuery)keyTable.get(FreenetURIHelper.getComparablePart(key));

-               if (key.startsWith("SSK@") || key.startsWith("USK@")
-                   || key.startsWith("KSK@") || key.startsWith("CHK@"))
-                       isAKey = true;
-               else
-                       isAKey = false;
+                       if (q != null)
+                               return q;

-               while(interrupted) {
-                       interrupted = false;
-
-                       try {
-                               for(it = runningQueries.iterator();
-                                   it.hasNext(); )
-                                       {
-                                               final FCPTransferQuery plop = 
(FCPTransferQuery)it.next();
-                                               if (isAKey) {
-                                                       if ((plop.getFileKey() 
== key)
-                                                           || 
key.equals(plop.getFileKey()))
-                                                               return plop;
-                                               } else {
-                                                       if ((plop.getFilename() 
== key)
-                                                           || 
key.equals(plop.getFilename()))
-                                                               return plop;
-                                               }
-                                       }
-
-                               for(int i = 0 ; i <= 
FCPQueueManager.PRIORITY_MIN ; i++) {
-                                       for(it = pendingQueries[i].iterator();
-                                           it.hasNext(); )
-                                               {
-                                                       final FCPTransferQuery 
plop = (FCPTransferQuery)it.next();
-                                                       if (isAKey) {
-                                                               if 
((plop.getFileKey() == key)
-                                                                   || 
key.equals(plop.getFileKey()))
-                                                                       return 
plop;
-                                                       } else {
-                                                               if 
((plop.getFilename() == key)
-                                                                   || 
key.equals(plop.getFilename()))
-                                                                       return 
plop;
-                                                       }
-                                               }
-
-                               }
-                       } catch(final java.util.ConcurrentModificationException 
e) {
-                               Logger.notice(this, "getTransfer(): Collission. 
Reitering");
-                               interrupted = true;
-                       }
-
+                       return 
(FCPTransferQuery)filenameTable.get(FreenetURIHelper.getFilenameFromKey(key));
                }

-               return null;
+               return (FCPTransferQuery)filenameTable.get(key);
        }


        /**
-        * Not reliable
-        */
-       public FCPTransferQuery getTransferByFilename(final String name) {
-               boolean interrupted=true;
-
-               Iterator it;
-
-               if (name == null)
-                       return null;
-
-               while(interrupted) {
-                       interrupted = false;
-
-                       try {
-                               for(it = runningQueries.iterator();
-                                   it.hasNext(); )
-                                       {
-                                               final FCPTransferQuery plop = 
(FCPTransferQuery)it.next();
-
-                                               if ((plop.getFilename() == name)
-                                                   || 
name.equals(plop.getFilename()))
-                                                       return plop;
-                                       }
-
-                               for(int i = 0 ; i <= 
FCPQueueManager.PRIORITY_MIN ; i++) {
-                                       for(it = pendingQueries[i].iterator();
-                                           it.hasNext(); )
-                                               {
-                                                       final FCPTransferQuery 
plop = (FCPTransferQuery)it.next();
-
-                                                       if ((plop.getFilename() 
== name)
-                                                           || 
name.equals(plop.getFilename()))
-                                                               return plop;
-                                               }
-
-                               }
-                       } catch(final java.util.ConcurrentModificationException 
e) {
-                               Logger.notice(this, "getTransferByFilename(): 
Collission. Reitering");
-                               interrupted = true;
-                       }
-
-               }
-
-               return null;
-       }
-
-
-       /**
         * Compare using the key.
         */
        public boolean isAlreadyPresent(final FCPTransferQuery query) {

Modified: trunk/apps/Thaw/src/thaw/gui/JDragTree.java
===================================================================
--- trunk/apps/Thaw/src/thaw/gui/JDragTree.java 2007-01-25 03:40:46 UTC (rev 
11612)
+++ trunk/apps/Thaw/src/thaw/gui/JDragTree.java 2007-01-25 07:03:17 UTC (rev 
11613)
@@ -57,6 +57,7 @@
 import javax.swing.JLabel;
 import javax.swing.JTree;
 import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
 import javax.swing.tree.DefaultTreeModel;
 import javax.swing.tree.TreeModel;
 import javax.swing.tree.TreeNode;
@@ -226,11 +227,11 @@
                                                         return;
                                                 }

-                                                final DefaultMutableTreeNode 
sourceNode = (DefaultMutableTreeNode)pathSource.getLastPathComponent();
-                                                final DefaultMutableTreeNode 
oldParent = (DefaultMutableTreeNode)sourceNode.getParent();
+                                                final MutableTreeNode 
sourceNode = (MutableTreeNode)pathSource.getLastPathComponent();
+                                                final MutableTreeNode 
oldParent = (MutableTreeNode)sourceNode.getParent();

-                                                final DefaultMutableTreeNode 
targetNode = (DefaultMutableTreeNode)pathTarget.getLastPathComponent();
-                                                final DefaultMutableTreeNode 
newParent = (DefaultMutableTreeNode)targetNode.getParent();
+                                                final MutableTreeNode 
targetNode = (MutableTreeNode)pathTarget.getLastPathComponent();
+                                                final MutableTreeNode 
newParent = (MutableTreeNode)targetNode.getParent();

                                                 if( !sourceNode.isLeaf() && 
(targetNode.getParent() == sourceNode) )
                                                 {
@@ -266,7 +267,8 @@
                                                                 // ... and 
insert into newParent
                                                                 if( idx >= 
newParent.getChildCount() )
                                                                 {
-                                                                        
newParent.add( sourceNode );
+                                                                        
//newParent.add( sourceNode );
+                                                                        
newParent.insert(sourceNode, newParent.getChildCount());
                                                                         final 
int insertedIndex[] = { newParent.getChildCount()-1 };
                                                                         
model.nodesWereInserted( newParent, insertedIndex );
                                                                 }

Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -96,6 +96,11 @@
 thaw.config.nodeAddress=Node address
 thaw.config.nodePort=Node port (FCP)

+thaw.config.sameComputerButNotLocalhost.l0=You've specified that the 
connection must be made on
+thaw.config.sameComputerButNotLocalhost.l1=another IP than 127.0.0.1 but 
you've specified also that
+thaw.config.sameComputerButNotLocalhost.l2=Thaw and the node are on the same 
computer.
+thaw.config.sameComputerButNotLocalhost.l4=I hope you're sure of your 
parameters.
+
 thaw.config.maxSimultaneousDownloads=Maximum simultaneous downloads (-1 = 
unlimited)
 thaw.config.maxSimultaneousInsertions=Maximum simultaneous insertions (-1 = 
unlimited)

@@ -190,7 +195,6 @@

 ## About
 thaw.about.title=About
-thaw.about.l1=Thaw
 thaw.about.l2=by Jerome Flesch
 thaw.about.l3=2006(c) Freenet Project Incorporated
 thaw.about.l4=under GPLv2
@@ -278,7 +282,12 @@
 thaw.plugin.index.export=Export
 thaw.plugin.index.import=Import
 thaw.plugin.index.export.indexKeys=Index keys + folders
-thaw.plugin.index.export.all=Indexes keys + folders + file lists + link lists
+thaw.plugin.index.export.all=Index keys + folders + file lists + link lists
 thaw.plugin.index.importedFolderName=Imported indexes

+thaw.plugin.index.nonInserted=non-inserted

+thaw.plugin.index.markAllAsSeen=Mark all as seen
+thaw.plugin.index.markAsSeen=Mark as seen
+
+thaw.plugin.index.publishPrivateKey=Attach the private key with the index

Modified: trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -178,7 +178,6 @@

 ## About
 thaw.about.title=? propos
-thaw.about.l1=Thaw
 thaw.about.l2=par J?r?me Flesch
 thaw.about.l3=2006(c) Freenet Project Incorporated
 thaw.about.l4=sous GPLv2

Modified: trunk/apps/Thaw/src/thaw/plugins/Hsqldb.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/Hsqldb.java        2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/Hsqldb.java        2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -83,6 +83,8 @@
                        Logger.error(this, "SQLException while closing 
connection !");
                        e.printStackTrace();
                }
+
+               Logger.info(this, "Done.");
        }

        public String getNameForUser() {
@@ -107,6 +109,6 @@
        }

        public javax.swing.ImageIcon getIcon() {
-               return null;
+               return thaw.core.IconBox.database;
        }
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java  2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java  2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -60,15 +60,8 @@

                boolean newDb;

-               newDb = false;
+               newDb = DatabaseManager.init(hsqldb, core.getConfig(), 
core.getSplashScreen());

-               if (core.getConfig().getValue("indexDatabaseVersion") == null) {
-                       newDb = true;
-                       core.getConfig().setValue("indexDatabaseVersion", "1");
-               }
-
-               DatabaseManager.createTables(hsqldb);
-
                browserPanel = new IndexBrowserPanel(hsqldb, 
core.getQueueManager(), core.getConfig(), core.getMainWindow());
                setMainWindow(core.getMainWindow());
                core.getMainWindow().getTabbedPane().addChangeListener(this);
@@ -115,6 +108,8 @@
                if (autoRefresh != null)
                        autoRefresh.stop();

+               browserPanel.stopAllThreads();
+
                core.getMainWindow().getTabbedPane().removeChangeListener(this);

                if (browserPanel != null) {

Modified: trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/ToolbarModifier.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -66,7 +66,7 @@
        public void displayButtonsInTheToolbar() {
                if (mainWindow != null) {
                        if (areDisplayed && mainWindow.getLastToolbarModifier() 
== this) {
-                               Logger.notice(this, "Already displayed !");
+                               Logger.debug(this, "Already displayed !");
                                return;
                        }


Modified: trunk/apps/Thaw/src/thaw/plugins/index/AutoRefresh.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/AutoRefresh.java     2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/AutoRefresh.java     2007-01-25 
07:03:17 UTC (rev 11613)
@@ -8,7 +8,7 @@

 import thaw.fcp.FCPQueueManager;

-public class AutoRefresh implements Runnable {
+public class AutoRefresh implements Runnable, java.util.Observer {

        public final static boolean DEFAULT_ACTIVATED = true;
        public final static int DEFAULT_INTERVAL = 300;
@@ -87,48 +87,33 @@
                        ResultSet results;
                        int ret;

-                       st = c.prepareStatement("SELECT id, originalName, 
displayName, publicKey, privateKey, author, positionInTree, revision "+
-                                               "FROM indexes WHERE id > ? 
ORDER by id LIMIT 1");
+                       if (lastIdx != -1) {
+                               st = c.prepareStatement("SELECT id, 
originalName, displayName, publicKey, privateKey, author, positionInTree, 
revision "+
+                                                       "FROM indexes WHERE id 
> ? ORDER by id LIMIT 1");

-                       if (lastIdx != -1) {
                                st.setInt(1, lastIdx);
-                               if (st.execute())
-                                       results = st.getResultSet();
-                               else
-                                       return -1;
+
+                               results = st.executeQuery();
                        } else {
                                results = db.executeQuery("SELECT id, 
originalName, displayName, publicKey, privateKey, author, positionInTree, 
revision "+
                                                          "FROM indexes ORDER 
by Id LIMIT 1");
-
-                               if (results == null)
-                                       return -1;
                        }

-                       if (!results.next())
+                       if (results == null || !results.next())
                                return -1;

                        ret = results.getInt("id");

                        Index index;

-                       index = 
browserPanel.getIndexTree().getRegisteredIndex(results.getString("publicKey"));
+                       index = new Index(browserPanel.getDb(),
+                                         results.getInt("id"));

-                       if (index == null)
-                               index = new Index(queueManager, browserPanel,
-                                                 results.getInt("id"), null,
-                                                 
results.getString("originalName"),
-                                                 
results.getString("displayName"),
-                                                 
results.getString("publicKey"),
-                                                 
results.getString("privateKey"),
-                                                 results.getInt("revision"),
-                                                 results.getString("author"));
+                       index.downloadFromFreenet(this, 
browserPanel.getIndexTree(), queueManager);

-                       if (index.getPrivateKey() != null) {
-                               Logger.debug(this, "Private key found ! index 
ignored");
-                               return ret;
-                       }
+                       browserPanel.getIndexTree().redraw();

-                       index.updateFromFreenet(-1);
+                       browserPanel.getIndexProgressBar().addTransfer(1);

                        return ret;

@@ -139,6 +124,25 @@
        }


+       public void update(java.util.Observable o, Object param) {
+
+               if (((Index)o).hasChanged())
+                       browserPanel.getIndexTree().refresh();
+               else
+                       browserPanel.getIndexTree().redraw();
+
+               if 
(o.equals(browserPanel.getTables().getFileTable().getFileList())) {
+                       browserPanel.getTables().getFileTable().refresh();
+               }
+
+               if 
(o.equals(browserPanel.getTables().getLinkTable().getLinkList())) {
+                       browserPanel.getTables().getLinkTable().refresh();
+               }
+               browserPanel.getUnknownIndexList().addLinks((LinkList)o);
+               browserPanel.getIndexProgressBar().removeTransfer(1);
+       }
+
+
        public void run() {
                int lastIdx = -1;

@@ -165,4 +169,5 @@
                        threadRunning = false;
        }

+
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java 2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/DatabaseManager.java 2007-01-25 
07:03:17 UTC (rev 11613)
@@ -18,27 +18,39 @@
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.w3c.dom.Text;
+import java.util.Vector;
+import java.util.Iterator;


 import thaw.core.Logger;
+import thaw.core.Config;
+import thaw.core.SplashScreen;
 import thaw.plugins.Hsqldb;
 import thaw.fcp.FCPQueueManager;

 /**
  * Creates all the tables used to save the indexes,
  * manages structure changes if needed, etc.
+ *
+ * <br/> TAKE CARE: because of the conversion mechanisms, the field order is 
NOT ALWAYS the same !
+ *       So DON'T DO "SELECT * [...]" !
+ *
  * <br/>
  * "Comprenne qui pourra" :P
  *
  * <pre>
- * indexCategories (name, positionInTree)
- *  |-- indexCategories (name, positionInTree)
+ * indexFolders (id, name, positionInTree)
+ *  |-- indexFolders (id, name, positionInTree)
  *  | |-- [...]
  *  |
- *  |-- indexes (name, publicKey, [privateKey], positionInTree)
- *    |-- links (indexName, indexPublicKey)
- *    |-- files (filename, publicKey, mime, size)
- *      |-- metadatas (name, value)
+ *  |-- indexes (id, realName, displayName, publicKey, [privateKey], 
positionInTree, newRev, publishPrivateKey (0/1))
+ *    |-- links (id, indexName, indexPublicKey)
+ *    |-- files (id, filename, publicKey, mime, size)
+ *      |-- metadatas (id, name, value)
+ *
+ * indexParents(indexId, folderId) # table de jointure
+ * folderParents(folderId, parentId) # table de jointure
+ *
  * </pre>
  *
  * positionInTree == position in its JTree branch.
@@ -49,42 +61,100 @@

        }

+
        /**
+        * @splashScreen can be null
+        * @return true if database is a new one
+        */
+       public static boolean init(Hsqldb db, Config config, SplashScreen 
splashScreen) {
+               boolean newDb;
+
+               newDb = false;
+
+               if (config.getValue("indexDatabaseVersion") == null) {
+                       newDb = true;
+                       config.setValue("indexDatabaseVersion", "2");
+               } else {
+
+                       /* CONVERTIONS */
+
+                       if 
("1".equals(config.getValue("indexDatabaseVersion"))) {
+                               if (splashScreen != null)
+                                       splashScreen.setStatus("Converting 
database ...");
+                               if (convertDatabase_1_to_2(db))
+                                       config.setValue("indexDatabaseVersion", 
"2");
+                               /* else
+                                * TODO : Put a warning here and stop the 
plugin loading
+                                */
+                       }
+
+                       /* ... */
+               }
+
+
+               createTables(db);
+
+               return newDb;
+       }
+
+
+       /**
         * Can be safely called, even if the tables already exist.
         */
        public static void createTables(final Hsqldb db) {
                //sendQuery(db,
                //        "SET IGNORECASE TRUE");
-               DatabaseManager.sendQuery(db,
-                         "CREATE CACHED TABLE indexCategories ("
+
+               sendQuery(db,
+                         "CREATE CACHED TABLE indexFolders ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "name VARCHAR(255) NOT NULL,"
                          + "positionInTree INTEGER NOT NULL,"
                          + "modifiableIndexes BOOLEAN NOT NULL," /* Obsolete */
                          + "parent INTEGER NULL,"
                          + "PRIMARY KEY (id),"
-                         + "FOREIGN KEY (parent) REFERENCES indexCategories 
(id))");
+                         + "FOREIGN KEY (parent) REFERENCES indexFolders 
(id))");

-               DatabaseManager.sendQuery(db,
+               sendQuery(db,
                          "CREATE CACHED TABLE indexes ("
                          + "id INTEGER IDENTITY NOT NULL, "
                          + "originalName VARCHAR(255) NOT NULL, "
                          + "displayName VARCHAR(255) NULL, "
                          + "publicKey VARCHAR(255) NOT NULL, "
                          + "privateKey VARCHAR(255) NULL, "
+                         + "publishPrivateKey BOOLEAN DEFAULT FALSE NOT NULL, "
                          + "author VARCHAR(255) NULL, "
                          + "positionInTree INTEGER NOT NULL, "
                          + "revision INTEGER NOT NULL, "
-                         + "parent INTEGER NULL, "
+                         + "newRev BOOLEAN DEFAULT FALSE NOT NULL, "
+                         + "parent INTEGER NULL, " /* direct parent */
                          + "PRIMARY KEY (id), "
-                         + "FOREIGN KEY (parent) REFERENCES indexCategories 
(id))");
+                         + "FOREIGN KEY (parent) REFERENCES indexFolders 
(id))");

-               DatabaseManager.sendQuery(db,
+               /* direct AND indirect parents */
+               sendQuery(db, /* this table avoid some horrible recursivities */
+                         "CREATE CACHED TABLE indexParents ("
+                         + "indexId INTEGER NOT NULL,"
+                         + "folderId INTEGER NULL)");
+               //+ "FOREIGN KEY (indexId) REFERENCES indexes (id)"
+               //+ "FOREIGN KEY (folderId) REFERENCES indexFolders (id))");
+
+
+               /* direct AND indirect parents */
+               sendQuery(db, /* this table avoid some horrible recursivities */
+                         "CREATE CACHED TABLE folderParents ("
+                         + "folderId INTEGER NOT NULL,"
+                         + "parentId INTEGER NULL)");
+               //+ "FOREIGN KEY (folderId) REFERENCES indexFolders (id)"
+               //+ "FOREIGN KEY (parentId) REFERENCES indexFolders (id))");
+
+
+               sendQuery(db,
                          "CREATE CACHED TABLE categories ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "name VARCHAR(255) NOT NULL)");

-               DatabaseManager.sendQuery(db,
+               sendQuery(db,
                          "CREATE CACHED TABLE files ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "filename VARCHAR(255) NOT NULL,"
@@ -94,11 +164,12 @@
                          + "size BIGINT NOT NULL,"
                          + "category INTEGER NULL,"
                          + "indexParent INTEGER NOT NULL,"
+                         + "toDelete BOOLEAN DEFAULT FALSE NOT NULL,"
                          + "PRIMARY KEY (id),"
                          + "FOREIGN KEY (indexParent) REFERENCES indexes (id),"
                          + "FOREIGN KEY (category) REFERENCES categories 
(id))");

-               DatabaseManager.sendQuery(db,
+               sendQuery(db,
                          "CREATE CACHED TABLE links ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "publicKey VARCHAR(350) NOT NULL," // key ~= 100 + 
filename == 255 max
@@ -106,17 +177,18 @@
                          + "comment VARCHAR(512) NOT NULL,"
                          + "indexParent INTEGER NOT NULL,"
                          + "indexTarget INTEGER NULL,"
+                         + "toDelete BOOLEAN DEFAULT false NOT NULL,"
                          + "PRIMARY KEY (id),"
                          + "FOREIGN KEY (indexParent) REFERENCES indexes (id),"
                          + "FOREIGN KEY (indexTarget) REFERENCES indexes 
(id))");

-               DatabaseManager.sendQuery(db,
+               sendQuery(db,
                          "CREATE CACHED TABLE metadataNames ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "name VARCHAR(255) NOT NULL,"
                          + "PRIMARY KEY (id))");

-               DatabaseManager.sendQuery(db,
+               sendQuery(db,
                          "CREATE CACHED TABLE metadatas ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "nameId INTEGER NOT NULL,"
@@ -128,30 +200,58 @@

        }

+
        public static void dropTables(final Hsqldb db) {
-               DatabaseManager.sendQuery(db, "DROP TABLE metadatas");
-               DatabaseManager.sendQuery(db, "DROP TABLE metadataNames");
+               /* TODO : Add a warning here */

-               DatabaseManager.sendQuery(db, "DROP TABLE files");
-               DatabaseManager.sendQuery(db, "DROP TABLE links");
+               sendQuery(db, "DROP TABLE metadatas");
+               sendQuery(db, "DROP TABLE metadataNames");

-               DatabaseManager.sendQuery(db, "DROP TABLE indexes");
-               DatabaseManager.sendQuery(db, "DROP TABLE indexCategories");
+               sendQuery(db, "DROP TABLE files");
+               sendQuery(db, "DROP TABLE links");
+
+               sendQuery(db, "DROP TABLE indexes");
+               sendQuery(db, "DROP TABLE indexCategories");
        }


        /**
         * Returns no error / Throws no exception.
+        * @return false if an exception happened
         */
-       protected static void sendQuery(final Hsqldb db, final String query) {
+       protected static boolean sendQuery(final Hsqldb db, final String query) 
{
                try {
                        db.executeQuery(query);
+                       return true;
                } catch(final SQLException e) {
                        Logger.notice(new DatabaseManager(), "While 
(re)creating sql tables: "+e.toString());
+                       return false;
                }
        }


+       public static int getNextId(Hsqldb db, String table) {
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("SELECT id FROM "+
+                                                                        
table+" ORDER BY id DESC "+
+                                                                        " 
LIMIT 1");
+                               ResultSet res = st.executeQuery();
+
+                               if (res.next())
+                                       return (res.getInt("id") + 1);
+                               else
+                                       return 1;
+
+                       } catch(SQLException e) {
+                               Logger.error(new DatabaseManager(), "Unable to 
get next id because: "+e.toString());
+                       }
+
+                       return -1;
+       }
+
+
        public static int getNmbIndexes(Hsqldb db) {
                int nmb;

@@ -284,11 +384,236 @@

                Element e = 
(Element)rootEl.getElementsByTagName("indexCategory").item(0);

-               IndexCategory importCategory = 
indexBrowser.getIndexTree().getRoot().getNewImportFolder();
+               IndexFolder importCategory = 
indexBrowser.getIndexTree().getRoot().getNewImportFolder(indexBrowser.getDb());

-               importCategory.do_import(e);
+               importCategory.do_import(indexBrowser, e);

+               indexBrowser.getIndexTree().getRoot().forceReload();
+               indexBrowser.getIndexTree().refresh();
+
                Logger.info(new DatabaseManager(), "Import done");

        }
+
+
+
+       /**
+        * used by convertDatabase_1_to_2()
+        */
+       public static boolean insertChildIn(Hsqldb db, int folderId) throws 
SQLException {
+               java.util.Vector results;
+               int i = 0, j;
+
+               Logger.notice(new DatabaseManager(), "Expanding folder 
"+Integer.toString(folderId));
+
+               PreparedStatement st;
+
+               st = db.getConnection().prepareStatement("SELECT id FROM 
indexFolders WHERE "+
+                                                        ((folderId >= 0) ? 
"parent = ?" : "parent IS NULL"));
+
+               if (folderId >= 0)
+                       st.setInt(1, folderId);
+
+               ResultSet set = st.executeQuery();
+               results = new java.util.Vector();
+
+               while(set.next()) {
+                       results.add(new Integer(set.getInt("id")));
+               }
+
+               for (java.util.Iterator it = results.iterator();
+                    it.hasNext();) {
+                       int nextId = ((Integer)it.next()).intValue();
+
+                       if (!insertChildIn(db, nextId)) {
+                               Logger.error(new DatabaseManager(), "halted");
+                               return false;
+                       }
+
+                       i++;
+
+                       st = db.getConnection().prepareStatement("SELECT 
folderId FROM folderParents WHERE parentId = ?");
+                       st.setInt(1, nextId);
+
+                       Vector childFolders = new Vector();
+
+                       j = 0;
+
+                       ResultSet rs = st.executeQuery();
+
+                       while(rs.next()) {
+                               j++;
+                               childFolders.add(new 
Integer(rs.getInt("folderId")));
+                       }
+
+                       for (Iterator ite = childFolders.iterator();
+                            ite.hasNext();) {
+                               Integer a = (Integer)ite.next();
+
+                               st = 
db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, 
parentId) "+
+                                                                        
"VALUES (?, ?)");
+                               st.setInt(1, a.intValue());
+                               if (folderId < 0)
+                                       st.setNull(2, Types.INTEGER);
+                               else
+                                       st.setInt(2, folderId);
+
+                               st.execute();
+                       }
+
+
+
+                       st = db.getConnection().prepareStatement("SELECT 
indexId FROM indexParents WHERE folderId = ?");
+                       st.setInt(1, nextId);
+
+                       Vector childIndexes = new Vector();
+
+                       rs = st.executeQuery();
+
+                       while(rs.next()) {
+                               j++;
+                               childIndexes.add(new 
Integer(rs.getInt("indexId")));
+                       }
+
+                       if (j == 0) {
+                               Logger.warning(new DatabaseManager(), "empty 
folder (id = "+Integer.toString(nextId)+") ?");
+                       }
+
+                       for (Iterator ite = childIndexes.iterator();
+                            ite.hasNext();) {
+                               Integer a = (Integer)ite.next();
+
+                               st = 
db.getConnection().prepareStatement("INSERT INTO indexParents (indexId, 
folderId) "+
+                                                                        
"VALUES (?, ?)");
+                               st.setInt(1, a.intValue());
+                               if (folderId < 0)
+                                       st.setNull(2, Types.INTEGER);
+                               else
+                                       st.setInt(2, folderId);
+
+                               st.execute();
+                       }
+
+               }
+
+               Logger.notice(new DatabaseManager(), Integer.toString(i) + " 
child folder found for folder "+Integer.toString(folderId));
+
+               return true;
+       }
+
+
+
+       public static boolean convertDatabase_1_to_2(Hsqldb db) {
+               if (!sendQuery(db, "ALTER TABLE indexCategories RENAME TO 
indexFolders")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting the database (1 to 2) (renaming table indexCategories to 
indexfolders)");
+                       return false;
+               }
+
+
+               if (!sendQuery(db, "ALTER TABLE indexes ADD COLUMN newRev 
BOOLEAN DEFAULT false")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting the database (1 to 2) ! (adding column 'newRev' to the index 
table)");
+                       return false;
+               }
+
+               if (!sendQuery(db, "ALTER TABLE indexes ADD COLUMN 
publishPrivateKey BOOLEAN DEFAULT false")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting the database (1 to 2) ! (adding column 'publishPrivateKey' to the 
index table)");
+                       return false;
+               }
+
+               if (!sendQuery(db, "ALTER TABLE links ADD COLUMN toDelete 
BOOLEAN DEFAULT false")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting the database (1 to 2) ! (adding column to link table)");
+               }
+
+               if (!sendQuery(db, "ALTER TABLE files ADD COLUMN toDelete 
BOOLEAN DEFAULT false")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting the database (1 to 2) ! (adding column to file table)");
+               }
+
+               /* direct AND indirect parents */
+               if (!sendQuery(db, /* this table avoid some horrible 
recusirvities */
+                              "CREATE CACHED TABLE indexParents ("
+                              + "indexId INTEGER NOT NULL,"
+                              + "folderId INTEGER NULL)")) {
+                       Logger.error(new DatabaseManager(), "Unable to create 
table because");
+                       return false;
+               }
+
+               /* direct AND indirect parents */
+               if (!sendQuery(db, /* this table avoid some horrible 
recursivities */
+                              "CREATE CACHED TABLE folderParents ("
+                              + "folderId INTEGER NOT NULL,"
+                              + "parentId INTEGER NULL)")) {
+                       Logger.error(new DatabaseManager(), "Unable to create 
table because");
+                       return false;
+               }
+
+
+               if (!sendQuery(db,
+                              "INSERT INTO folderParents (folderId, parentId) 
"+
+                              "SELECT id, parent FROM indexFolders")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting (1_2_1)");
+                       return false;
+               }
+
+               if (!sendQuery(db,
+                              "INSERT INTO indexParents (indexId, folderId) "+
+                              "SELECT id, parent FROM indexes")) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting (1_2_2)");
+                       return false;
+               }
+
+
+               try {
+                       insertChildIn(db, -1);
+               } catch(SQLException e) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting : "+e.toString());
+                       return false;
+               }
+
+
+               /* convert SSK into USK */
+
+               try {
+                       PreparedStatement st;
+
+                       st = db.getConnection().prepareStatement("SELECT id, 
publicKey, originalName, revision FROM indexes");
+
+                       PreparedStatement subSt;
+                       subSt = db.getConnection().prepareStatement("UPDATE 
indexes "+
+                                                                   "SET 
publicKey = ? "+
+                                                                   "WHERE id = 
?");
+
+                       ResultSet set = st.executeQuery();
+
+                       while(set.next()) {
+                               String key = set.getString("publicKey");
+
+                               if (key != null && key.startsWith("SSK@")) {
+                                       int id = set.getInt("id");
+                                       String name = 
set.getString("originalName");
+                                       int rev = set.getInt("revision");
+
+                                       String newKey;
+
+                                       if (key.endsWith("/"))
+                                               newKey = 
key.replaceFirst("SSK@", "USK@")+name+"/"+rev+"/"+name+".frdx";
+                                       else
+                                               newKey = 
key.replaceFirst("SSK@", "USK@")+"/"+name+"/"+rev+"/"+name+".frdx";
+
+                                       Logger.notice(new DatabaseManager(), 
"Replacing "+key+" with "+newKey);
+
+                                       subSt.setString(1, newKey);
+                                       subSt.setInt(2, id);
+
+                                       subSt.execute();
+                               }
+                       }
+
+               } catch(SQLException e) {
+                       Logger.error(new DatabaseManager(), "Error while 
converting SSK into USK : "+e.toString());
+                       return false;
+               }
+
+               return true;
+       }
+
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/File.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/File.java    2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/File.java    2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -6,6 +6,8 @@
 import java.sql.Types;
 import java.util.Iterator;
 import java.util.Vector;
+import java.util.Observer;
+import java.util.Observable;

 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -21,517 +23,305 @@
 import thaw.plugins.Hsqldb;
 import thaw.plugins.insertPlugin.DefaultMIMETypes;

-public class File extends java.util.Observable implements java.util.Observer {
+public class File implements Observer {
+       private Hsqldb db = null;
        private int id = -1; /* -1 = undefined */

-       private String fileName;
-       private String publicKey;
-       private String mime;
-       private long size = -1;
-       private String category;
+       private String filename = null;
+       private String publicKey = null;
+       private java.io.File localPath = null;
+       private String mime = null;
+       private long size = 0;

-       private String localPath = null;
-       private FCPTransferQuery transfer = null; /* can be null */
-
-       private Index parent;
        private int parentId;

-       private Hsqldb db;
-
-       private FCPQueueManager queueManager = null;
-
-
-       public File(final Hsqldb db, final String publicKey, final Index 
parent) {
-               if (db == null)
-                       Logger.error(this, "No ref. to the database ?!");
-
+       public File(final Hsqldb db, final int id) {
                this.db = db;
-               id = -1;
-               this.publicKey = publicKey;
-               deduceFilenameFromKey();
-
-               size = 0;
+               this.id = id;
+               reloadDataFromDb(id);
        }

-       /**
-        * @param path Local path
-        * @param transfer Corresponding tranfer (can be null).
-        */
-       public File(final Hsqldb db, final String path, final String category, 
final Index parent, final FCPTransferQuery transfer) {
+       public File(final Hsqldb db, final int id, final String filename,
+                   String publicKey, java.io.File localPath,
+                   String mime, long size, int parentId) {
                this.db = db;
-
-               if (db == null)
-                       Logger.error(this, "No ref. to the database ?! (2)");
-
-               id = -1;
-               localPath = path;
-               this.transfer = transfer;
-
-               final String[] pathElements = 
localPath.split(java.io.File.separator.replaceAll("\\\\", "\\\\\\\\"));
-               fileName = pathElements[pathElements.length-1];
-
-               size = (new java.io.File(path)).length();
-
-               this.category = category;
-               setParent(parent);
-
-               if(transfer != null)
-                       ((java.util.Observable)transfer).addObserver(this);
+               this.id = id;
+               this.filename = filename;
+               this.publicKey = publicKey;
+               this.localPath = localPath;
+               this.mime = mime;
+               this.size = size;
+               this.parentId = parentId;
        }


-       public File(final Hsqldb db, final ResultSet resultSet, final Index 
parent) throws SQLException {
-               this.db = db;
+       public void update(Observable o, Object param) {
+               if (o instanceof FCPClientPut) {
+                       FCPClientPut put = (FCPClientPut)o;

-               if (db == null)
-                       Logger.error(this, "No ref. to the database ?! (3)");
+                       String key = put.getFileKey();

-               id = resultSet.getInt("id");
-               fileName = resultSet.getString("filename").trim();
-               publicKey = resultSet.getString("publicKey").trim();
-               localPath = resultSet.getString("localPath");
-               size = resultSet.getLong("size");
-               parentId = resultSet.getInt("indexParent");
-               //category = resultSet.getString("category");
+                       if (FreenetURIHelper.isAKey(key)) {
+                               setPublicKey(key);
+                               o.deleteObserver(this);
+                       }

-               deduceFilenameFromKey();
+                       return;
+               }

-               this.parent = parent;
+               Logger.error(this, "Unknow object: "+o.toString());
        }

-       public File(final Hsqldb db, final Element fileElement, final Index 
parent) {
-               this.db = db;

-               if (db == null)
-                       Logger.error(this, "No ref. to the database ?! (4)");
+       public void reloadDataFromDb(int id) {
+               this.id = id;

-               id = Integer.parseInt(fileElement.getAttribute("id")); /* will 
be changed when inserted in the database */
-               publicKey = fileElement.getAttribute("key");
+               try {
+                       PreparedStatement st;

-               if (publicKey != null)
-                       publicKey = publicKey.trim();
+                       st = db.getConnection().prepareStatement("SELECT 
filename, publicKey, localPath, mime, size, indexParent "+
+                                                                " FROM files 
WHERE id = ? LIMIT 1");

-               localPath = null;
+                       st.setInt(1, id);

-               size = Long.parseLong(fileElement.getAttribute("size"));
+                       ResultSet rs = st.executeQuery();

-               setOptions(fileElement.getChildNodes());
+                       if (rs.next()) {
+                               String lp;

-               deduceFilenameFromKey();
+                               filename = rs.getString("filename");
+                               publicKey = rs.getString("publicKey");
+                               lp = rs.getString("localPath");
+                               localPath = (lp == null ? null : new 
java.io.File(lp));
+                               mime = rs.getString("mime");
+                               size = rs.getLong("size");
+                               parentId = rs.getInt("indexParent");
+                       } else {
+                               Logger.error(this, "File 
'"+Integer.toString(id)+"' not found");
+                       }

-               this.parent = parent;
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to get info for file 
'"+Integer.toString(id)+"'");
+               }
        }

-       public void deduceFilenameFromKey() {
-               fileName = FreenetURIHelper.getFilenameFromKey(publicKey);
-       }
+       public void setParent(int parent_id) {
+               try {
+                       PreparedStatement st;

-       public void setOptions(final NodeList list) {
-               for(int i = 0 ; i < list.getLength() ; i++) {
-                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
-                               final Element option = (Element)list.item(i);
-
-                               if("category".equals( 
option.getAttribute("name") ))
-                                       category = option.getAttribute("value");
-                               else {
-                                       /* TODO */
-                               }
-                       }
+                       st = db.getConnection().prepareStatement("UPDATE files 
SET indexParent = ? "+
+                                                                "WHERE id = 
?");
+                       st.setInt(1, parent_id);
+                       st.setInt(2, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to set parent: 
"+e.toString());
                }
        }

-       public void setParent(final Index parent) {
-               this.parent = parent;
-               if (parent != null)
-                       parentId = parent.getId();
-               else
-                       parentId = -1;
-       }
+       public String getFilename() {
+               if (filename == null)
+                       reloadDataFromDb(id);

-       public Index getParent() {
-               return parent;
+               return filename;
        }

-       public int getParentId() {
-               return parentId;
-       }
-
-       public String getFilename() {
-               return fileName;
-       }
-
        public long getSize() {
                return size;
        }

        public String getLocalPath() {
-               return localPath;
-       }
+               if (localPath == null)
+                       reloadDataFromDb(id);

-       public String getCategory() {
-               return category;
+               if (localPath == null)
+                       return null;
+
+               return localPath.getAbsolutePath();
        }

        public String getPublicKey() {
+               if (publicKey == null)
+                       reloadDataFromDb(id);
+
                return publicKey;
        }

-       public void setPublicKey(final String publicKey) {
-               this.publicKey = publicKey;

-               if (publicKey != null && !publicKey.equals(this.publicKey)) {
-                       this.publicKey = publicKey;
-                       update();
-               }
-               else
-                       this.publicKey = publicKey;
+       public FCPTransferQuery getTransfer(FCPQueueManager q) {
+               FCPTransferQuery tr;

-               setChanged();
-               this.notifyObservers();
-       }
+               tr = q.getTransfer(getPublicKey());

-       public FCPTransferQuery getTransfer() {
-               return transfer;
-       }
+               if (tr == null || (tr.isFinished() && tr.isSuccessful()))
+                       return null;

-       public void setTransfer(final FCPTransferQuery query) {
-               if (transfer != null) {
-                       Logger.notice(this, "A transfer is already running for 
this file");
-                       return;
-               }
-
-               transfer = query;
-
-               if (transfer != null) {
-                       if(transfer instanceof FCPClientPut)
-                               ((FCPClientPut)transfer).addObserver(this);
-                       if(transfer instanceof FCPClientGet)
-                               ((FCPClientGet)transfer).addObserver(this);
-               }
-
-               if (transfer != null)
-                       update(((java.util.Observable)transfer), null);
-
-               setChanged();
-               this.notifyObservers(query);
+               return tr;
        }

+       public void setPublicKey(final String publicKey) {
+               this.publicKey = publicKey;

-       public void recalculateCHK(final FCPQueueManager queueManager) {
-               this.queueManager = queueManager;
+               try {
+                       PreparedStatement st;

-               if (getLocalPath() == null) {
-                       Logger.notice(this, "Trying to recalculate key from a 
file where we don't have the local path");
-                       return;
-               }
+                       st = db.getConnection().prepareStatement("UPDATE files 
SET publicKey = ? "+
+                                                                "WHERE id = 
?");

-               final FCPClientPut insertion = new FCPClientPut(new 
java.io.File(getLocalPath()), 0, 0, null,
-                                                         null, 4,
-                                                         true, 2, true); /* 
getCHKOnly */
-               queueManager.addQueryToThePendingQueue(insertion);
-
-               this.setTransfer(insertion);
+                       st.setString(1, publicKey);
+                       st.setInt(2, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to set publicKey: 
"+e.toString());
+               }
        }

-       public void download(final String targetPath, final FCPQueueManager 
queueManager) {
-               if (!FreenetURIHelper.isAKey(getPublicKey())) {
-                       Logger.warning(this, "Can't start download: file key is 
unknown");
-                       return;
-               }

-               if (getTransfer() != null && getTransfer().isRunning()) {
-                       Logger.warning(this, "Can't download: a transfer is 
already running");
-                       return;
-               }
+       public void setSize(final long size) {
+               this.publicKey = publicKey;

-               final FCPClientGet clientGet = new FCPClientGet(getPublicKey(), 
4, 0, true, -1, targetPath);
+               try {
+                       PreparedStatement st;

-               queueManager.addQueryToThePendingQueue(clientGet);
+                       st = db.getConnection().prepareStatement("UPDATE files 
SET size = ? "+
+                                                                "WHERE id = 
?");

-               setTransfer(clientGet);
-       }
-
-
-       public void insertOnFreenet(final FCPQueueManager queueManager) {
-               if (getTransfer() != null && getTransfer().isRunning()) {
-                       Logger.warning(this, "Another transfer is already 
running : can't insert");
-                       return;
+                       st.setLong(1, size);
+                       st.setInt(2, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to set publicKey: 
"+e.toString());
                }
-
-               final FCPClientPut clientPut = new FCPClientPut(new 
java.io.File(getLocalPath()),
-                                                         0, 0, null, null, 4, 
true, 0);
-               queueManager.addQueryToThePendingQueue(clientPut);
-
-               setTransfer(clientPut);
        }


-       /* Try to find its download automagically */
-       public void setTransfer(final FCPQueueManager queueManager) {
-               if ((publicKey != null) || (fileName != null)) {
-                       FCPTransferQuery trans;
-
-                       if (getPublicKey() == null)
-                               trans = queueManager.getTransfer(getFilename());
-                       else
-                               trans = 
queueManager.getTransfer(getPublicKey());
-
-                       if (trans == null) {
-                               trans = 
queueManager.getTransferByFilename(fileName);
-                       }
-
-                       setTransfer(trans);
+       public FCPClientPut recalculateCHK(final FCPQueueManager queueManager) {
+               if (localPath == null) {
+                       Logger.notice(this, "Trying to recalculate key from a 
file where we don't have the local path");
+                       return null;
                }

-               setChanged();
-               notifyObservers();
-       }
-
-       public void insert() {
-               if (parent == null) {
-                       Logger.notice(this, "insert(): No parent !");
-                       return;
+               if (getTransfer(queueManager) != null) {
+                       Logger.notice(this, "Another transfer is already 
running for this file");
+                       return null;
                }

-               synchronized (db.dbLock) {
-                       try {
-                               PreparedStatement st;
+               final FCPClientPut insertion = new FCPClientPut(localPath, 0, 
0, null,
+                                                               null, 4,
+                                                               true, 2, true); 
/* getCHKOnly */
+               queueManager.addQueryToTheRunningQueue(insertion);

-                               st = 
db.getConnection().prepareStatement("SELECT id FROM files ORDER BY id DESC 
LIMIT 1");
+               insertion.addObserver(this);

-                               try {
-                                       if(st.execute()) {
-                                               final ResultSet result = 
st.getResultSet();
-                                               result.next();
-                                               id = result.getInt("id")+1;
-                                       } else
-                                               id = 1;
-                               } catch(final SQLException e) {
-                                       id = 1;
-                               }
+               return insertion;
+       }


-                               st = 
db.getConnection().prepareStatement("INSERT INTO files (id, filename, 
publicKey, "+
-                                               "localPath, mime, size, 
category, indexParent) "+
-                               "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
-                               st.setInt(1, id);
+       public FCPClientGet download(final String targetPath, final 
FCPQueueManager queueManager) {
+               FCPTransferQuery q;
+               String publicKey = getPublicKey();

-                               st.setString(2, fileName);
-
-                               if(publicKey != null)
-                                       st.setString(3, publicKey);
-                               else
-                                       st.setString(3, fileName);
-
-                               if(localPath != null)
-                                       st.setString(4, localPath);
-                               else
-                                       st.setNull(4, Types.VARCHAR);
-
-                               if(mime != null)
-                                       st.setString(5, mime);
-                               else
-                                       st.setNull(5, Types.VARCHAR);
-
-                               st.setLong(6, size);
-
-                               if(category != null)
-                                       st.setString(7, category);
-                               else
-                                       st.setNull(7, Types.VARCHAR);
-
-                               st.setInt(8, parent.getId());
-
-                               st.execute();
-                       } catch(final SQLException e) {
-                               Logger.error(this, "Unable to insert file 
'"+fileName+"' because: "+e.toString());
-                       }
+               if (publicKey == null) {
+                       Logger.notice(this, "No key !");
+                       return null;
                }
-       }

-       public void delete() {
-
-               try {
-                       PreparedStatement st;
-
-                       st = db.getConnection().prepareStatement("DELETE FROM 
files WHERE id = ?");
-                       st.setInt(1, id);
-
-                       st.execute();
-
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to remove file 
'"+fileName+"' because: "+e.toString());
+               if (!FreenetURIHelper.isAKey(publicKey)) {
+                       Logger.warning(this, "Can't start download: file key is 
unknown");
+                       return null;
                }
-       }

-       public void update() {
-               if (parent == null) {
-                       Logger.notice(this, "update(): No parent !");
-                       return;
+               if ( (q = getTransfer(queueManager)) != null && q.isRunning()) {
+                       Logger.warning(this, "Can't download: a transfer is 
already running");
+                       return null;
                }

-               try {
-                       PreparedStatement st;
+               final FCPClientGet clientGet = new FCPClientGet(publicKey, 4, 
0, true, -1, targetPath);

-                       st = db.getConnection().prepareStatement("UPDATE files 
SET filename = ?, publicKey = ?, localPath = ?, mime= ?, size = ?, category = 
?, indexParent = ? WHERE id = ?");
+               queueManager.addQueryToThePendingQueue(clientGet);

-                       st.setString(1, fileName);
+               return clientGet;
+       }

-                       if(publicKey != null)
-                               st.setString(2, publicKey);
-                       else
-                               st.setString(2, fileName);

-                       if(localPath != null)
-                               st.setString(3, localPath);
-                       else
-                               st.setNull(3, Types.VARCHAR);
+       public FCPClientPut insertOnFreenet(final FCPQueueManager queueManager) 
{
+               FCPTransferQuery q;
+               String localPath;

-                       if(mime != null)
-                               st.setString(4, mime);
-                       else
-                               st.setNull(4, Types.VARCHAR);
+               if ( (q = getTransfer(queueManager)) != null && q.isRunning()) {
+                       Logger.warning(this, "Another transfer is already 
running : can't insert");
+                       return null;
+               }

-                       st.setLong(5, size);
+               localPath = getLocalPath();

-                       if(category != null)
-                               st.setString(6, category);
-                       else
-                               st.setNull(6, Types.VARCHAR);
+               if (localPath == null) {
+                       Logger.warning(this, "No local path => can't insert");
+                       return null;
+               }

-                       st.setInt(7, getParent().getId());
+               final FCPClientPut clientPut = new FCPClientPut(new 
java.io.File(localPath),
+                                                               0, 0, null, 
null, 4, true, 0);
+               queueManager.addQueryToThePendingQueue(clientPut);

-                       st.setInt(8, id);
+               clientPut.addObserver(this);

-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to update file 
'"+fileName+"' because: "+e.toString());
-               }
+               return clientPut;
        }


-       public boolean isInTheDatabase() {
-               if (parent == null) {
-                       Logger.notice(this, "isInTheDatabase(): No parent !");
-                       return false;
-               }
+       public int getId() {
+               return id;
+       }

+       public int getParentId() {
                try {
                        PreparedStatement st;

-                       st = db.getConnection().prepareStatement("SELECT 
publicKey from files WHERE publicKey = ? AND indexParent = ?");
+                       st = db.getConnection().prepareStatement("SELECT 
indexParent FROM files "+
+                                                                "WHERE id = ? 
LIMIT 1");
+                       st.setInt(1, id);

-                       if(publicKey != null)
-                               st.setString(1, publicKey);
-                       else
-                               st.setString(1, fileName);
+                       ResultSet rs = st.executeQuery();

-                       st.setInt(2, getParent().getId());
-
-                       if(st.execute()) {
-                               final ResultSet result = st.getResultSet();
-                               if ((result != null) && result.next())
-                                       return true;
+                       if (rs.next()) {
+                               return rs.getInt("indexParent");
+                       } else {
+                               Logger.error(this, "File id not found: 
"+Integer.toString(id));
                        }

-               } catch(final SQLException e) {
-
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to get parent id because: 
"+e.toString());
                }

-               return false;
+               return -1;
        }


-       public void update(final java.util.Observable o, final Object param) {
-               if(o == transfer) {
-                       if (transfer.getFileKey() != null)
-                               setPublicKey(transfer.getFileKey());
-
-                       if (transfer.isFinished() && (transfer instanceof 
FCPClientPut)) {
-                               if (queueManager != null) {
-                                       queueManager.remove(transfer);
-                                       queueManager = null;
-                               }
-
-                               ((FCPClientPut)transfer).deleteObserver(this);
-                               setPublicKey(transfer.getFileKey());
-                               update();
-                       }
-
-                       if(transfer.isFinished() && (transfer instanceof 
FCPClientGet)) {
-                               ((FCPClientGet)transfer).deleteObserver(this);
-
-                               if (transfer.getPath() != null) {
-                                       java.io.File file = new 
java.io.File(transfer.getPath());
-
-                                       if (file.exists() && file.isFile())
-                                               size = file.length();
-                               }
-
-                       }
-
-                       if(transfer.isFinished() && transfer.isSuccessful()) {
-                               transfer = null;
-                       }
-
-                       setChanged();
-                       this.notifyObservers();
-               }
-       }
-
-       public int getId() {
-               return id;
-       }
-
-
        public Element getXML(final Document xmlDoc) {
-               if(getPublicKey() == null) {
-                       Logger.notice(this, "No public key for file 
'"+fileName+"' => not added to the index");
-                       return null;
-               }
-
-               final Element file = xmlDoc.createElement("file");
-
-               file.setAttribute("id", Integer.toString(getId()));
-               file.setAttribute("key", getPublicKey());
-               file.setAttribute("size", Long.toString(getSize()));
-               file.setAttribute("mime", 
DefaultMIMETypes.guessMIMEType(fileName));
-
-               for(final Iterator it = getOptionElements(xmlDoc).iterator();
-                   it.hasNext(); ) {
-                       final Element e = (Element)it.next();
-                       file.appendChild(e);
-               }
-
-               return file;
+               /* TODO */
+               return null;
        }

-       /**
-        * @return Element Vector
-        */
-       public Vector getOptionElements(final Document xmlDoc) {
-               final Vector options = new Vector();

-               if(category != null) {
-                       final Element categoryEl = 
xmlDoc.createElement("option");
-                       categoryEl.setAttribute("name", "category");
-                       categoryEl.setAttribute("value", category);
+       public void delete() {
+               try {
+                       PreparedStatement st;

-                       options.add(categoryEl);
+                       st = db.getConnection().prepareStatement("DELETE FROM 
files WHERE id = ?");
+                       st.setInt(1, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to remove file because: 
"+e.toString());
                }
-
-               return options;
        }

+
        /**
-        * Modifiable in the database
+        * Modifiable in the database<br/>
+        * Note: Do a SQL requests each time
         */
        public boolean isModifiable() {
-               if (getParent() == null) {
-                       Logger.warning(this, "No parent ?!");
-                       return false;
-               }
-
-               return getParent().isModifiable();
+               return (new Index(db, parentId)).isModifiable();
        }
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/FileList.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileList.java        2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileList.java        2007-01-25 
07:03:17 UTC (rev 11613)
@@ -7,18 +7,5 @@
  */
 public interface FileList {

-       public void loadFiles(String fileColumnToSort, boolean asc);
-
-       /**
-        * Must returns a copy of the vector it's using !
-        */
-       public Vector getFileList();
-
-
-       public thaw.plugins.index.File getFile(int index);
-
-       /**
-        * Can update the database.
-        */
-       public void unloadFiles();
+       public Vector getFileList(String columnToSort, boolean asc);
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/FileManagementHelper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileManagementHelper.java    
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileManagementHelper.java    
2007-01-25 07:03:17 UTC (rev 11613)
@@ -37,13 +37,15 @@
        public static class FileDownloader implements FileAction {
                private FCPQueueManager queueManager;
                private AbstractButton actionSource;
+               private IndexBrowserPanel indexBrowser;
                private Vector target;
                private Config config;

-               public FileDownloader(final Config config, final 
FCPQueueManager queueManager, final AbstractButton actionSource) {
+               public FileDownloader(final Config config, final 
FCPQueueManager queueManager, IndexBrowserPanel indexBrowser, final 
AbstractButton actionSource) {
                        this.queueManager = queueManager;
                        this.actionSource = actionSource;
                        this.config = config;
+                       this.indexBrowser = indexBrowser;
                        if (actionSource != null)
                                actionSource.addActionListener(this);
                }
@@ -72,32 +74,38 @@

                        config.setValue("lastDestinationDirectory", 
destination.getPath());

-                       FileManagementHelper.downloadFiles(queueManager, 
target, destination.getPath());
+                       FileManagementHelper.downloadFiles(queueManager, 
indexBrowser, target, destination.getPath());
                }
        }


        /**
         * @param files See thaw.plugins.index.File
+        * @param indexBrowser can be null
         */
-       public static void downloadFiles(final FCPQueueManager queueManager,
+       public static void downloadFiles(final FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser,
                                         final Vector files, final String 
destinationPath) {
                for (final Iterator it = files.iterator();
                     it.hasNext();) {
                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
                        file.download(destinationPath, queueManager);
                }
+
+               if (indexBrowser != null)
+                       indexBrowser.getTables().getFileTable().refresh();
        }


        public static class FileInserter implements FileAction {
                private FCPQueueManager queueManager;
                private AbstractButton actionSource;
+               private IndexBrowserPanel indexBrowser;
                private Vector target;

-               public FileInserter(final FCPQueueManager queueManager, final 
AbstractButton actionSource) {
+               public FileInserter(final FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
                        this.queueManager = queueManager;
                        this.actionSource = actionSource;
+                       this.indexBrowser = indexBrowser;
                        if (actionSource != null)
                                actionSource.addActionListener(this);
                }
@@ -114,9 +122,7 @@
                                     it.hasNext(); ) {
                                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();

-                                       if ((file.getLocalPath() == null)
-                                           || !file.isModifiable()
-                                           || file.getTransfer() != null) {
+                                       if (file.getLocalPath() == null) {
                                                isOk = false;
                                                break;
                                        }
@@ -127,31 +133,38 @@
                }

                public void actionPerformed(final ActionEvent e) {
-                       FileManagementHelper.insertFiles(queueManager, target);
+                       FileManagementHelper.insertFiles(queueManager, 
indexBrowser, target);
                }
        }

        /**
         * @param files See thaw.plugins.index.File
+        * @param indexBrowser can be null
         */
        public static void insertFiles(final FCPQueueManager queueManager,
+                                      IndexBrowserPanel indexBrowser,
                                       final Vector files) {
                for (final Iterator it = files.iterator();
                     it.hasNext();) {
                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
                        file.insertOnFreenet(queueManager);
                }
+
+               if (indexBrowser != null)
+                       indexBrowser.getTables().getFileTable().refresh();
        }


        public static class FileKeyComputer implements FileAction {
                private FCPQueueManager queueManager;
+               private IndexBrowserPanel indexBrowser;
                private AbstractButton actionSource;
                private Vector target;

-               public FileKeyComputer(final FCPQueueManager queueManager, 
final AbstractButton actionSource) {
+               public FileKeyComputer(final FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
                        this.queueManager = queueManager;
                        this.actionSource = actionSource;
+                       this.indexBrowser = indexBrowser;
                        if (actionSource != null)
                                actionSource.addActionListener(this);
                }
@@ -167,9 +180,7 @@
                                     it.hasNext(); ) {
                                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();

-                                       if ((file.getLocalPath() == null)
-                                           || !file.isModifiable()
-                                           || file.getTransfer() != null) {
+                                       if (file.getLocalPath() == null) {
                                                isOk = false;
                                                break;
                                        }
@@ -181,33 +192,39 @@

                public void actionPerformed(final ActionEvent e) {
                        Logger.notice(this, "COMPUTING");
-                       FileManagementHelper.computeFileKeys(queueManager, 
target);
+                       FileManagementHelper.computeFileKeys(queueManager, 
indexBrowser, target);
                }
        }

        /**
         * @param files See thaw.plugins.index.File
+        * @param indexBrowser can be null
         */
        public static void computeFileKeys(final FCPQueueManager queueManager,
+                                          IndexBrowserPanel indexBrowser,
                                           final Vector files) {
                for (final Iterator it = files.iterator();
                     it.hasNext();) {
                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
                        file.recalculateCHK(queueManager);
                }
+
+               if (indexBrowser != null) {
+                       indexBrowser.getTables().getFileTable().refresh();
+               }
        }


        public static class FileRemover implements FileAction {
-               private FCPQueueManager queueManager;
+               private IndexBrowserPanel indexBrowser;
                private AbstractButton actionSource;
                private Vector target;

                /**
                 * @param queueManager is used to stop transfers if needed
                 */
-               public FileRemover(final FCPQueueManager queueManager, final 
AbstractButton actionSource) {
-                       this.queueManager = queueManager;
+               public FileRemover(final IndexBrowserPanel indexBrowser, final 
AbstractButton actionSource) {
+                       this.indexBrowser = indexBrowser;
                        this.actionSource = actionSource;
                        if (actionSource != null)
                                actionSource.addActionListener(this);
@@ -220,16 +237,14 @@

                        this.target = target;

-                       if (target != null) {
-                               for (final Iterator it = target.iterator();
-                                    it.hasNext();) {
-                                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                       if (target != null && target.size() > 0) {
+                               /* check just the first file */

-                                       if (!file.isModifiable()) {
-                                               isOk = false;
-                                               break;
-                                       }
-                               }
+                               thaw.plugins.index.File file = 
(thaw.plugins.index.File)target.get(0);
+
+                               if (!file.isModifiable())
+                                       isOk = false;
+
                        }


@@ -237,31 +252,23 @@
                }

                public void actionPerformed(final ActionEvent e) {
-                       FileManagementHelper.removeFiles(queueManager, target);
+                       FileManagementHelper.removeFiles(indexBrowser, target);
                }
        }

        /**
         * @param files See thaw.plugins.index.File / files must have their 
parent correctly set
-        * @param queueManager Used to stop the transfer if needed
         */
-       public static void removeFiles(final FCPQueueManager queueManager,
+       public static void removeFiles(final IndexBrowserPanel browserPanel,
                                       final Vector files) {
                for (final Iterator it = files.iterator();
                     it.hasNext();) {
                        final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
-                       final Index parent = file.getParent();

-                       if (parent == null) {
-                               Logger.warning(new FileManagementHelper(), 
"File '"+file.getFilename()+"' has no parent ?!");
-                               continue;
-                       }
+                       file.delete();
+               }

-                       if (file.getTransfer() != null)
-                               file.getTransfer().stop(queueManager);
-
-                       parent.removeFile(file);
-               }
+               browserPanel.getTables().getFileTable().refresh();
        }



Modified: trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -12,6 +12,7 @@
 import java.util.Observable;
 import java.util.Vector;

+import java.awt.Color;
 import javax.swing.JLabel;
 import javax.swing.JMenuItem;
 import javax.swing.JPanel;
@@ -63,13 +64,17 @@
        private int[] selectedRows;

        private IndexBrowserPanel indexBrowser;
+       private FCPQueueManager queueManager;

+       private TransferRefresher refresher;
+
        public FileTable(final FCPQueueManager queueManager, IndexBrowserPanel 
indexBrowser, final Config config) {
                this.indexBrowser = indexBrowser;
+               this.queueManager = queueManager;

                fileListModel = new FileListModel();
                table = new JTable(fileListModel);
-               table.setShowGrid(true);
+               table.setShowGrid(false);
                table.setDefaultRenderer( table.getColumnClass(0), new 
FileRenderer() );

                table.addMouseListener(this);
@@ -98,34 +103,34 @@
                item = new 
JMenuItem(I18n.getMessage("thaw.common.action.download"));
                button = new JButton(IconBox.downloads);
                
button.setToolTipText(I18n.getMessage("thaw.common.action.download"));
-               toolbarActions.add(new 
FileManagementHelper.FileDownloader(config, queueManager, button));
+               toolbarActions.add(new 
FileManagementHelper.FileDownloader(config, queueManager, indexBrowser, 
button));
                toolbarModifier.addButtonToTheToolbar(button);
                rightClickMenu.add(item);
-               rightClickActions.add(new 
FileManagementHelper.FileDownloader(config, queueManager, item));
+               rightClickActions.add(new 
FileManagementHelper.FileDownloader(config, queueManager, indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.insert"));
                button = new JButton(IconBox.insertions);
                
button.setToolTipText(I18n.getMessage("thaw.plugin.index.insert"));
-               toolbarActions.add(new 
FileManagementHelper.FileInserter(queueManager, button));
+               toolbarActions.add(new 
FileManagementHelper.FileInserter(queueManager, indexBrowser, button));
                toolbarModifier.addButtonToTheToolbar(button);
                rightClickMenu.add(item);
-               rightClickActions.add(new 
FileManagementHelper.FileInserter(queueManager, item));
+               rightClickActions.add(new 
FileManagementHelper.FileInserter(queueManager, indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.recalculateKeys"));
                button = new JButton(IconBox.key);
                
button.setToolTipText(I18n.getMessage("thaw.plugin.index.recalculateKeys"));
-               toolbarActions.add(new 
FileManagementHelper.FileKeyComputer(queueManager, button));
+               toolbarActions.add(new 
FileManagementHelper.FileKeyComputer(queueManager, indexBrowser, button));
                toolbarModifier.addButtonToTheToolbar(button);
                rightClickMenu.add(item);
-               rightClickActions.add(new 
FileManagementHelper.FileKeyComputer(queueManager, item));
+               rightClickActions.add(new 
FileManagementHelper.FileKeyComputer(queueManager, indexBrowser, item));

                item = new JMenuItem(I18n.getMessage("thaw.common.remove"));
                button = new JButton(IconBox.delete);
                button.setToolTipText(I18n.getMessage("thaw.common.remove"));
-               toolbarActions.add(new 
FileManagementHelper.FileRemover(queueManager, button));
+               toolbarActions.add(new 
FileManagementHelper.FileRemover(indexBrowser, button));
                toolbarModifier.addButtonToTheToolbar(button);
                rightClickMenu.add(item);
-               rightClickActions.add(new 
FileManagementHelper.FileRemover(queueManager, item));
+               rightClickActions.add(new 
FileManagementHelper.FileRemover(indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.common.copyKeysToClipboard"));
                rightClickMenu.add(item);
@@ -136,8 +141,17 @@
                gotoItem.addActionListener(this);

                updateRightClickMenu(null);
+
+               refresher = new TransferRefresher();
+               Thread th = new Thread(refresher);
+               th.start();
        }

+       public void stopRefresher() {
+               refresher.stop();
+       }
+
+
        public ToolbarModifier getToolbarModifier() {
                return toolbarModifier;
        }
@@ -169,38 +183,31 @@
        }

        protected Vector getSelectedFiles(final int[] selectedRows) {
-               final Vector srcList = fileList.getFileList();
+               final Vector srcList = fileList.getFileList(null, false);
                final Vector files = new Vector();

                for(int i = 0 ; i < selectedRows.length ; i++) {
-                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)srcList.get(selectedRows[i]);
-                       files.add(file);
+                       files.add(srcList.get(selectedRows[i]));
                }

                return files;
        }

        public void setFileList(final FileList fileList) {
-               if(this.fileList != null) {
-                       this.fileList.unloadFiles();
-               }
-
-               if(fileList != null) {
-                       fileList.loadFiles(sortColumn, ascOrder);
-               }
-
                this.fileList = fileList;

                fileListModel.reloadFileList(fileList);
        }


+       public FileList getFileList() {
+               return fileList;
+       }
+
+
        public void mouseClicked(final MouseEvent e) {
                Vector selection;

-               if (fileList instanceof Index)
-                       ((Index)fileList).setChanged(false);
-
                if (fileList == null) {
                        selectedRows = null;
                        return;
@@ -242,38 +249,8 @@
                        if (selectedRows.length <= 0)
                                return;

-                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)fileList.getFileList().get(selectedRows[0]);
+                       /* TODO : Re-do it :p */

-                       if (file.getParentId() == -1) {
-                               Logger.notice(this, "No parent ? abnormal");
-                               return;
-                       }
-
-                       Index parent;
-
-                       if (file.getParent() == null)
-                               parent = 
indexBrowser.getIndexTree().getRoot().getIndex(file.getParentId());
-                       else
-                               parent = file.getParent();
-
-                       if (parent == null) {
-                               Logger.notice(this, "Cannot find again the 
parent ?! Id: "+Integer.toString(file.getParentId()));
-                               return;
-                       }
-
-                       
indexBrowser.getIndexTree().getTree().setSelectionPath(new 
TreePath(parent.getTreeNode().getPath()));
-
-                       indexBrowser.getTables().setList(parent);
-
-                       int row;
-
-                       row = parent.getFilePosition(file);
-
-                       if (row < 0)
-                               Logger.notice(this, "File not found in the 
index ?! Index : "+parent.getPublicKey()+" ; File: " +file.getPublicKey());
-                       else
-                               setSelectedRows(row, row);
-
                        return;
                }
        }
@@ -284,7 +261,12 @@
        }


-       public class FileListModel extends javax.swing.table.AbstractTableModel 
implements java.util.Observer {
+       public void refresh() {
+               fileListModel.refresh();
+       }
+
+
+       public class FileListModel extends javax.swing.table.AbstractTableModel 
{
                private static final long serialVersionUID = 1L;

                public Vector columnNames;
@@ -307,35 +289,17 @@
                }

                public void reloadFileList(final FileList newFileList) {
-                       if((fileList != null) && (fileList instanceof 
Observable)) {
-                               ((Observable)fileList).deleteObserver(this);
-                       }
-
-                       if((newFileList != null) && (newFileList instanceof 
Observable)) {
-                               ((Observable)newFileList).addObserver(this);
-                       }
-
                        fileList = newFileList;

-                       if(files != null) {
-                               for(final Iterator it = files.iterator();
-                                   it.hasNext(); ) {
-                                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
-                                       file.deleteObserver(this);
-                               }
-                       }
+                       refresh();
+               }

-                       files = null;
-
-                       if(fileList != null) {
-                               files = fileList.getFileList();
-                       }
-
-                       this.refresh();
+               public Vector getFiles() {
+                       return files;
                }

                public int getRowCount() {
-                       if(files == null)
+                       if (files == null)
                                return 0;

                        return files.size();
@@ -381,15 +345,18 @@

                        }

-                       if (column == 3)
-                               return file.getTransfer();
+                       if (column == 3) {
+                               return file.getTransfer(queueManager);
+                       }

                        return null;
                }

                public void refresh() {
                        if(fileList != null) {
-                               files = fileList.getFileList();
+                               files = fileList.getFileList(null, false);
+                       } else {
+                               files = null;
                        }

                        final TableModelEvent event = new TableModelEvent(this);
@@ -404,18 +371,16 @@
                public void refresh(final TableModelEvent e) {
                        fireTableChanged(e);
                }
-
-               public void update(final java.util.Observable o, final Object 
param) {
-                       this.refresh(); /* TODO : Do it more nicely ... :) */
-               }
        }


        private class FileRenderer extends DefaultTableCellRenderer {
                private final static long serialVersionUID = 20060821;

+               private Color softGray;
+
                public FileRenderer() {
-
+                       softGray = new Color(240,240,240);
                }

                public Component getTableCellRendererComponent(final JTable 
table, final Object value,
@@ -430,15 +395,19 @@
                                final FCPTransferQuery query = 
(FCPTransferQuery)value;
                                final JProgressBar bar = new JProgressBar(0, 
100);

+                               int progress;
+
                                bar.setStringPainted(true);
                                bar.setBorderPainted(false);

-                               if(((query instanceof FCPClientPut) && 
(query.getProgression() > 0))
-                                  || ((query instanceof FCPClientGet) && 
(query.getProgression() < 100)) )
-                                       bar.setValue(query.getProgression());
+                               if ((query instanceof FCPClientPut && 
(query.getTransferWithTheNodeProgression() < 100))
+                                   || ((query instanceof FCPClientGet) && 
(query.getTransferWithTheNodeProgression() <= 0)))
+                                       progress = 
query.getTransferWithTheNodeProgression();
                                else
-                                       
bar.setValue(query.getTransferWithTheNodeProgression());
+                                       progress = query.getProgression();

+                               bar.setValue(progress);
+
                                if(query.isFinished() && !query.isSuccessful())
                                        
bar.setString(I18n.getMessage("thaw.common.failed"));

@@ -446,24 +415,72 @@
                                        
bar.setString(I18n.getMessage("thaw.common.ok"));

                                if(!query.isFinished()) {
-                                       bar.setString(query.getStatus());
+                                       bar.setString(query.getStatus() +
+                                                     " [ 
"+Integer.toString(progress)+"% ]");
                                }

                                return bar;
                        }

+                       Component cell;
+
                        if(value instanceof Long)
-                               return 
super.getTableCellRendererComponent(table,
+                               cell = 
super.getTableCellRendererComponent(table,
                                                                           
thaw.plugins.queueWatcher.QueueTableModel.getPrintableSize(((Long)value).longValue()),
                                                                           
isSelected, hasFocus, row, column);
-
-                       final Component cell = 
super.getTableCellRendererComponent(table, value,
+                       else
+                               cell = 
super.getTableCellRendererComponent(table, value,
                                                                             
isSelected, hasFocus,
                                                                             
row, column);
-
+                       if (!isSelected) {
+                               if (row % 2 == 0)
+                                       cell.setBackground(Color.WHITE);
+                               else
+                                       cell.setBackground(softGray);
+                       }
                        return cell;
                }

        }

+
+       private class TransferRefresher implements Runnable {
+               private boolean running;
+
+               public TransferRefresher() {
+                       running = true;
+               }
+
+               public void run() {
+                       int i, max;
+
+                       while(running) {
+                               try {
+                                       Thread.sleep(5000);
+                               } catch(InterruptedException e) {
+                                       /* \_o< */
+                               }
+
+                               if (!running)
+                                       return;
+
+                               if (fileListModel.getFiles() == null)
+                                       continue;
+
+                               i = 0;
+
+                               for (Iterator it = 
fileListModel.getFiles().iterator() ;
+                                    it.hasNext(); i++) {
+                                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                                       if (file.getTransfer(queueManager) != 
null)
+                                               fileListModel.refresh(i);
+                               }
+                       }
+               }
+
+               public void stop() {
+                       running = false;
+               }
+       }
+
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/Index.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -12,8 +12,13 @@
 import java.sql.Types;
 import java.util.Iterator;
 import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Observer;
+import java.util.Observable;

 import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.transform.OutputKeys;
@@ -31,6 +36,7 @@

 import thaw.core.FreenetURIHelper;
 import thaw.core.Logger;
+import thaw.core.I18n;
 import thaw.fcp.FCPClientGet;
 import thaw.fcp.FCPClientPut;
 import thaw.fcp.FCPGenerateSSK;
@@ -38,947 +44,779 @@
 import thaw.fcp.FCPTransferQuery;
 import thaw.plugins.Hsqldb;

-public class Index extends java.util.Observable implements FileAndLinkList, 
IndexTreeNode, java.util.Observer {
+import thaw.plugins.insertPlugin.DefaultMIMETypes;

-       private final Hsqldb db;

-       private int id;
-       private IndexCategory parent;
-       private String realName;
-       private String displayName;

-       private String publicKey; /* without the filename ! */
-       private String privateKey;
+public class Index extends Observable implements MutableTreeNode, 
FileAndLinkList, IndexTreeNode, Observer {

-       private int revision = 0;
+       private final Hsqldb db;
+       private int id;
+       private TreeNode parentNode;

-       private Vector fileList;
-       private Vector linkList;

-       private DefaultMutableTreeNode treeNode;
+       private String publicKey = null;
+       /* needed for display: */
+       private String privateKey = null;
+       private int rev = -1;
+       private String displayName = null;
+       private boolean hasChanged = false;

-       private FCPGenerateSSK sskGenerator;

-       private final FCPQueueManager queueManager;
-       private final IndexBrowserPanel indexBrowser;
+       /* loaded only if asked explictly */
+       private String realName = null;

-       private FCPTransferQuery transfer = null;
-       private File targetFile = null;

-       private String author;
-
-       private boolean rewriteKey = true;
-       private boolean changed = false;
-
-       private boolean updateWhenKeyAreAvailable = false;
-
        /**
         * @deprecated Just don't use it !
         */
        public Index() {
                db = null;
-               queueManager = null;
-               indexBrowser = null;
        }

+       public Index(Hsqldb db, int id) {
+               this.db = db;
+               this.id = id;
+       }

        /**
-        * The bigest constructor of the world ...
-        * @param revision Ignored if the index is not modifiable (=> deduced 
from the publicKey)
+        * Use it when you can have these infos easily ; else let the index do 
the job
         */
-       public Index(final FCPQueueManager queueManager,
-                    final IndexBrowserPanel indexBrowser,
-                    final int id, final IndexCategory parent,
-                    String realName, String displayName,
-                    final String publicKey, final String privateKey,
-                    final int revision,
-                    final String author) {
-               this.indexBrowser = indexBrowser;
-               this.queueManager = queueManager;
-               treeNode = new DefaultMutableTreeNode(displayName, false);
-               this.db = indexBrowser.getDb();
+       public Index(Hsqldb db, int id, TreeNode parentNode, String publicKey, 
int rev, String privateKey, String displayName, boolean hasChanged) {
+               this(db, id);
+               this.parentNode = parentNode;
+               this.privateKey = privateKey;
+               this.publicKey = publicKey;
+               this.rev = rev;
+               this.displayName = displayName;
+               this.hasChanged = hasChanged;
+       }

+
+       /**
+        * Won't apply in the database !
+        */
+       public void setId(int id) {
                this.id = id;
-               this.parent = parent;
-               this.realName = realName.trim();
-               this.displayName = displayName.trim();
-
-               if (realName == null)
-                       realName = displayName;
-
-               if (displayName == null)
-                       displayName = realName;
-
-               this.revision = revision;
-
-               this.author = author;
-
-               setPrivateKey(privateKey);
-               setPublicKey(publicKey);
-
-               treeNode.setUserObject(this);
-
-               this.setTransfer();
        }


        /**
-        * Index registration allows to have a flat view of the loaded / 
displayed indexes
+        * Is this node coming from the tree ?
         */
-       public void register() {
-               indexBrowser.getIndexTree().registerIndex(this);
+       public boolean isInTree() {
+               return (getParent() != null);
        }

-       public void unregister() {
-               indexBrowser.getIndexTree().unregisterIndex(this);
+       public TreeNode getParent() {
+               return parentNode;
        }

+       public Enumeration children() {
+               return null;
+       }

-       public static boolean isDumbKey(final String key) {
-               return ((key == null) || key.equals("") || (key.length() < 20));
+       public boolean getAllowsChildren() {
+               return false;
        }

-       public void setParent(final IndexCategory parent) {
-               this.parent = parent;
+       public TreeNode getChildAt(int childIndex) {
+               return null;
        }

-       public IndexCategory getParent() {
-               return parent;
+       public int getChildCount() {
+               return 0;
        }

-       public DefaultMutableTreeNode getTreeNode() {
-               return treeNode;
+       /**
+        * relative to tree, not indexes :p
+        */
+       public int getIndex(TreeNode node) {
+               return -1;
        }

-       public Index getIndex(final int id) {
-               return (id == getId()) ? this : null;
+       public void setParent(MutableTreeNode newParent) {
+               parentNode = newParent;
+               setParent(((IndexTreeNode)newParent).getId());
        }

-       public void generateKeys() {
-               publicKey = null;
-               privateKey = null;
+       public void setParent(final int parentId) {
+               synchronized(db.dbLock) {

-               sskGenerator = new FCPGenerateSSK();
-               sskGenerator.addObserver(this);
-               sskGenerator.start(queueManager);
-       }
-
-       public boolean create() {
-               try {
-                       /* Rahh ! Hsqldb doesn't support getGeneratedKeys() ! 
8/ */
-                       synchronized (db.dbLock) {
-                               final Connection c = db.getConnection();
+                       Logger.info(this, 
"setParent("+Integer.toString(parentId)+")");
+                       try {
                                PreparedStatement st;

-                               st = c.prepareStatement("SELECT id FROM indexes 
ORDER BY id DESC LIMIT 1");
+                               st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                        "SET 
parent = ? "+
+                                                                        "WHERE 
id = ?");
+                               if (parentId >= 0)
+                                       st.setInt(1, parentId);
+                               else
+                                       st.setNull(1, Types.INTEGER);

+                               st.setInt(2, id);
+
                                st.execute();

-                               try {
-                                       final ResultSet key = st.getResultSet();
-                                       key.next();
-                                       id = key.getInt(1) + 1;
-                               } catch(final SQLException e) {
-                                       id = 1;
-                               }

-                               st = c.prepareStatement("INSERT INTO indexes 
(id, originalName, displayName, publicKey, privateKey, author, positionInTree, 
revision, parent) VALUES (?, ?,?,?,?,?, ?,?, ?)");
-                               st.setInt(1, id);
-                               st.setString(2, realName);
-                               st.setString(3, displayName);
-                               st.setString(4, publicKey != null ? publicKey : 
"");
-                               st.setString(5, privateKey);
-                               st.setString(6, author);
-                               st.setInt(7, 0);
+                               if (parentId >= 0) {
+                                       st = 
db.getConnection().prepareStatement("INSERT INTO indexParents (indexId, 
folderId) "+
+                                                                               
 " SELECT ?, parentId FROM folderParents "+
+                                                                               
 "   WHERE folderId = ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, parentId);

-                               st.setInt(8, revision);
+                                       st.execute();
+                               } /* else this parent has no parent ... :) */

-                               if((parent != null) && (parent.getId() >= 0))
-                                       st.setInt(9, parent.getId());
+                               st = 
db.getConnection().prepareStatement("INSERT INTO indexParents (indexId, 
folderId) "+
+                                                                        
"VALUES (?, ?)");
+
+                               st.setInt(1, id);
+                               if (parentId >= 0)
+                                       st.setInt(2, parentId);
                                else
-                                       st.setNull(9, Types.INTEGER);
+                                       st.setNull(2, Types.INTEGER);

                                st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while changing parent 
: "+e.toString());
                        }

-                       return true;
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to insert the new index in 
the db, because: "+e.toString());
-                       return false;
                }
-
        }

-       public void rename(final String name) {
-               try {
-                       final Connection c = db.getConnection();
+       /**
+        * entry point
+        */
+       public void removeFromParent() {
+               Logger.info(this, "removeFromParent()");
+
+               ((IndexFolder)parentNode).remove(this);
+
+               synchronized(db.dbLock) {
+
                        PreparedStatement st;

-                       st = c.prepareStatement("UPDATE indexes SET displayName 
= ? WHERE id = ?");
-                       st.setString(1, name);
-                       st.setInt(2, id);
-                       st.execute();
+                       try {
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexParents "+
+                                                                        "WHERE 
indexId = ?");
+                               st.setInt(1, id);
+                               st.execute();

-                       displayName = name;
-
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to rename the index 
'"+displayName+"' in '"+name+"', because: "+e.toString());
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while removing the 
index: "+e.toString());
+                       }
                }
+       }

+       public void remove(int index) {
+               /* nothing to do */
        }

-       public void delete() {
-               try {
-                       loadFiles(null, true);
-                       this.loadLinks(null, true);
+       public void remove(MutableTreeNode node) {
+               /* nothing to do */
+       }

-                       for(final Iterator fileIt = fileList.iterator(); 
fileIt.hasNext(); ) {
-                               final thaw.plugins.index.File file = 
(thaw.plugins.index.File)fileIt.next();
-                               file.delete();
-                       }
+       public void insert(MutableTreeNode child, int index) {
+               /* nothing to do */
+       }

-                       for (final Iterator linkIt = linkList.iterator(); 
linkIt.hasNext() ;) {
-                               final Link link = (Link)linkIt.next();
-                               link.delete();
-                       }
+       public boolean isLeaf() {
+               return true;
+       }

-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("DELETE 
FROM indexes WHERE id = ?");
-                       st.setInt(1, id);
-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to delete the index 
'"+displayName+"', because: "+e.toString());
-               }

-               if (transfer != null)
-                       transfer.stop(queueManager);
+       public void setUserObject(Object o) {
+               rename(o.toString());
        }

+       public MutableTreeNode getTreeNode() {
+               return this;
+       }

-       public void update() {
-               if (!Index.isDumbKey(publicKey) && Index.isDumbKey(privateKey)) 
/* non modifiable */
-                       return;

-               if (Index.isDumbKey(publicKey) && Index.isDumbKey(privateKey)) {
-                       generateKeys();
-                       updateWhenKeyAreAvailable = true;
-                       return;
-               }
+       public void rename(final String name) {
+               synchronized(db.dbLock) {

-               String tmpdir = System.getProperty("java.io.tmpdir");
+                       try {
+                               final Connection c = db.getConnection();
+                               PreparedStatement st;

-               if (tmpdir == null)
-                       tmpdir = "";
-               else
-                       tmpdir = tmpdir + java.io.File.separator;
+                               st = c.prepareStatement("UPDATE indexes SET 
displayName = ? WHERE id = ?");
+                               st.setString(1, name);
+                               st.setInt(2, id);
+                               st.execute();

-               targetFile = new java.io.File(tmpdir + realName +".frdx");
-
-               if (transfer != null) {
-                       Logger.notice(this, "A transfer is already running");
-                       return;
+                       } catch(final SQLException e) {
+                               Logger.error(this, "Unable to rename the index 
in '"+name+"', because: "+e.toString());
+                       }
                }

-               if(privateKey != null) {
-                       FCPClientPut clientPut;
+       }

-                       Logger.info(this, "Generating index ...");

-                       FileOutputStream outputStream;
+       public void delete() {
+               removeFromParent();

+               synchronized(db.dbLock) {
+
                        try {
-                               outputStream = new FileOutputStream(targetFile);
-                       } catch(final java.io.FileNotFoundException e) {
-                               Logger.warning(this, "Unable to create file 
'"+targetFile.toString()+"' ! not generated !");
-                               return;
-                       }

-                       generateXML(outputStream);
+                               PreparedStatement st;

-                       if(targetFile.exists()) {
-                               Logger.info(this, "Inserting new version");
+                               purgeFileList();
+                               purgeLinkList();

-                               revision++;
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexParents "+
+                                                                        "WHERE 
indexId = ?");
+                               st.setInt(1, id);
+                               st.execute();

-                               clientPut = new FCPClientPut(targetFile, 2, 
revision, realName, privateKey, 2, true, 0);
-                               clientPut.setMetadata("ContentType", 
"application/x-freenet-index");
-                               setTransfer(clientPut);
+                               Logger.notice(this, "DELETING AN INDEX");

-                               
queueManager.addQueryToThePendingQueue(clientPut);
-
-                               save();
-
-                       } else {
-                               Logger.warning(this, "Index not generated !");
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexes WHERE id = ?");
+                               st.setInt(1, id);
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to delete the index 
because : "+e.toString());
                        }
-
-                       setChanged();
-                       notifyObservers();
-               } else {
-                       updateFromFreenet(-1);
                }
-
        }

-       public void updateFromFreenet(final int rev) {
-               FCPClientGet clientGet;

-               if (transfer != null) {
-                       Logger.notice(this, "A transfer is already running !");
-                       return;
+       public void purgeLinkList() {
+               synchronized(db.dbLock) {
+
+                       try {
+                               final Connection c = db.getConnection();
+                               final PreparedStatement st = 
c.prepareStatement("DELETE FROM links WHERE indexParent = ?");
+                               st.setInt(1, getId());
+                               st.execute();
+                       } catch(final SQLException e) {
+                               Logger.error(this, "Unable to purge da list ! 
Exception: "+e.toString());
+                       }
                }
+       }

-               if (publicKey == null) {
-                       Logger.error(this, "No public key !! Can't get the 
index !");
-                       return;
+       public void purgeFileList() {
+               synchronized(db.dbLock) {
+                       try {
+                               final Connection c = db.getConnection();
+                               final PreparedStatement st = 
c.prepareStatement("DELETE FROM files WHERE indexParent = ?");
+                               st.setInt(1, getId());
+                               st.execute();
+                       } catch(final SQLException e) {
+                               Logger.error(this, "Unable to purge da list ! 
Exception: "+e.toString());
+                       }
                }
+       }

-               Logger.info(this, "Getting lastest version ...");
+       public int getId() {
+               return id;
+       }

-               String key;
+       public boolean loadData() {
+               Logger.info(this, "loadData()");
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st =
+                                       
db.getConnection().prepareStatement("SELECT publicKey, revision, privateKey, 
displayName FROM indexes WHERE id = ? LIMIT 1");

-               /* We will trust the node for the incrementation
-                  execept if a rev is specified */
+                               st.setInt(1, id);

+                               ResultSet set = st.executeQuery();

-               if (rev >= 0) {
-                       key = FreenetURIHelper.convertUSKtoSSK(publicKey);
-                       key = FreenetURIHelper.changeSSKRevision(key, rev, 0);
-                       rewriteKey = false;
-               } else {
-                       if (privateKey == null) {
-                               key = publicKey;
-                               rewriteKey = true;
-                       } else {
-                               key = getPublicKey();
-                               rewriteKey = false;
+                               if (set.next()) {
+                                       publicKey = set.getString("publicKey");
+                                       privateKey = 
set.getString("privateKey");
+                                       rev = set.getInt("revision");
+                                       displayName = 
set.getString("displayName");
+                                       return true;
+                               } else {
+                                       Logger.error(this, "Unable to find 
index "+Integer.toString(id)+" in the database ?!");
+                                       return false;
+                               }
+                       } catch (final SQLException e) {
+                               Logger.error(this, "Unable to get public key 
because: "+e.toString());
                        }
                }
+               return false;
+       }

-               Logger.info(this, "Key asked: "+key);

+       public String getPublicKey() {
+               if (publicKey == null) {
+                       loadData();
+               }

-               clientGet = new FCPClientGet(key, 2, 2, false, -1, null);
-               setTransfer(clientGet);
+               return publicKey;
+       }

-               /*
-                * These requests are usually quite fast, and don't consume a 
lot
-                * of bandwith / CPU. So we can skip the queue and start 
immediatly
-                * (and like this, they won't appear in the queue)
-                */
-               //this.queueManager.addQueryToThePendingQueue(clientGet);
-               clientGet.start(queueManager);
+       public int getRevision() {
+               if (rev < 0) {
+                       loadData();
+               }

-               this.setChanged();
-               this.notifyObservers();
+               return rev;
        }

-       public boolean isUpdating() {
-               return ((sskGenerator != null) || ((transfer != null) && 
(!transfer.isFinished())));
+       public String getPrivateKey() {
+               if (publicKey == null) { /* we rely on the publicKey because 
the privateKey is not often availabe */
+                       loadData();
+               }
+
+               return privateKey;
        }


-       protected void setTransfer(final FCPTransferQuery query) {
-               if (transfer != null && indexBrowser != null) {
-                       
indexBrowser.getIndexProgressBar().removeTransfer(query);
-               }
+       public boolean getPublishPrivateKey() {
+               try {

-               transfer = query;
+                       PreparedStatement st
+                               = db.getConnection().prepareStatement("SELECT 
publishPrivateKey FROM indexes WHERE id = ? LIMIT 1");

-               if (transfer != null) {
-                       if (transfer instanceof FCPClientGet)
-                               ((FCPClientGet)transfer).addObserver(this);
-                       if (transfer instanceof FCPClientPut)
-                               ((FCPClientPut)transfer).addObserver(this);
-                       this.update(((java.util.Observable)transfer), null);
-                       if (indexBrowser != null)
-                               
indexBrowser.getIndexProgressBar().addTransfer(query);
-               }
-       }
+                       st.setInt(1, id);

-       protected void setTransfer() {
-               if (queueManager == null || transfer != null)
-                       return;
+                       ResultSet set = st.executeQuery();

-               if (getPublicKey() != null) {
-                       if(!queueManager.isQueueCompletlyLoaded()) {
-                               final Thread th = new Thread(new 
WaitCompleteQueue());
-                               th.start();
-                               return;
+                       if (!set.next()) {
+                               Logger.error(this, "Unable to get 
publishPrivateKey value => not found !");
                        }

-                       String key;
+                       return set.getBoolean("publishPrivateKey");

-                       if (privateKey != null)
-                               key = 
FreenetURIHelper.getPublicInsertionSSK(getPublicKey());
-                       else
-                               key = getPublicKey();

-                       this.setTransfer(queueManager.getTransfer(key));
+               } catch(SQLException e){
+                       Logger.error(this, "Unable to get publishPrivateKey 
value because: "+e.toString());
                }

-               this.setChanged();
-               this.notifyObservers();
+               return false;
        }

-       private class WaitCompleteQueue implements Runnable {
-               public WaitCompleteQueue() { }
+       public void setPublishPrivateKey(boolean val) {
+               try {
+                       PreparedStatement st =
+                               db.getConnection().prepareStatement("UPDATE 
indexes "+
+                                                                   "SET 
publishPrivateKey = ? "+
+                                                                   "WHERE id = 
?");
+                       st.setBoolean(1, val);
+                       st.setInt(2, id);
+                       st.execute();

-               public void run() {
-                       int tryNumber = 0;
+               } catch(SQLException e){
+                       Logger.error(this, "Unable to set publishPrivateKey 
value because: "+e.toString());
+               }
+       }

-                       while(!queueManager.isQueueCompletlyLoaded() && 
(tryNumber < 120 /* 1min */)) {
-                               try {
-                                       Thread.sleep(500);
-                               } catch(final java.lang.InterruptedException e) 
{
-                                       /* \_o< */
-                               }

-                               tryNumber++;
-                       }
+       public void setPublicKey(String publicKey) {
+               int rev = FreenetURIHelper.getUSKRevision(publicKey);

-                       if (tryNumber == 120)
-                               return;
-
-                       Index.this.setTransfer();
-               }
+               setPublicKey(publicKey, rev);
        }


-       public void purgeLinkList() {
-               unloadLinks();
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("DELETE 
FROM links WHERE indexParent = ?");
-                       st.setInt(1, getId());
-                       st.execute();
-                       linkList = new Vector();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to purge da list ! 
Exception: "+e.toString());
-               }
-       }
+       /**
+        * Use directly this function only if you're sure that the rev is the 
same in the key
+        * @param publicKey must be an USK
+        */
+       public void setPublicKey(String publicKey, int rev) {
+               this.publicKey = publicKey;
+               this.rev = rev;

-       public void purgeFileList() {
-               unloadFiles();
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("DELETE 
FROM files WHERE indexParent = ?");
-                       st.setInt(1, getId());
-                       st.execute();
-                       fileList = new Vector();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to purge da list ! 
Exception: "+e.toString());
+               synchronized(db.dbLock) {
+
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                        "SET 
publicKey = ?, revision = ? "+
+                                                                        "WHERE 
id = ?");
+                               st.setString(1, publicKey);
+                               st.setInt(2, rev);
+                               st.setInt(3, id);
+
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to set public Key 
because: "+e.toString());
+                       }
                }
        }

-       public synchronized void save() {
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("UPDATE 
indexes SET originalName = ?, displayName = ?, publicKey = ?, privateKey = ?, 
positionInTree = ?, revision = ?, parent = ? , author = ? WHERE id = ?");

-                       st.setString(1, realName);
-                       st.setString(2, displayName);
-                       st.setString(3, publicKey != null ? publicKey : "");
-                       if(privateKey != null)
-                               st.setString(4, privateKey);
-                       else
-                               st.setNull(4, Types.VARCHAR);
+       public void setPrivateKey(String privateKey) {
+               if (privateKey != null && !FreenetURIHelper.isAKey(privateKey))
+                       privateKey = null;

-                       if ((treeNode != null) && (treeNode.getParent() != 
null))
-                               st.setInt(5, 
treeNode.getParent().getIndex(treeNode));
-                       else
-                               st.setInt(5, 0);
+               this.privateKey = privateKey;

-                       st.setInt(6, revision);
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

-                       if( treeNode.getParent() == null || 
((IndexTreeNode)treeNode.getParent()).getId() < 0)
-                               st.setNull(7, Types.INTEGER);
-                       else
-                               st.setInt(7, 
((IndexTreeNode)treeNode.getParent()).getId());
+                               st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                        "SET 
privateKey = ? "+
+                                                                        "WHERE 
id = ?");
+                               if (privateKey != null)
+                                       st.setString(1, privateKey);
+                               else
+                                       st.setNull(1, Types.VARCHAR);
+                               st.setInt(2, id);

-                       st.setString(8, author);
-
-                       st.setInt(9, getId());
-
-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to save index state 
'"+toString()+"' because : "+e.toString());
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to set private Key 
because: "+e.toString());
+                       }
                }
        }

-       public int getId() {
-               return id;
-       }

-       public String getPublicKey() {
-               if ((publicKey == null) || Index.isDumbKey(publicKey))
-                       return null;
+       public String getRealName() {
+               if (realName != null)
+                       return realName;

-               if (publicKey.startsWith("SSK@")) { /* as it should when 
privateKey is known */
-                       if (publicKey.endsWith("/"))
-                               return publicKey.replaceFirst("SSK@", 
"USK@")+realName+"/"+revision+"/"+realName+".frdx";
-                       else
-                               return publicKey.replaceFirst("SSK@", 
"USK@")+"/"+realName+"/"+revision+"/"+realName+".frdx";
-               } else
-                       return publicKey;
-       }

-       /**
-        * Always set the privateKey first
-        */
-       public void setPublicKey(final String key) {
-               if ((key != null) && !Index.isDumbKey(key))
-                       publicKey = key.trim();
-               else
-                       publicKey = null;
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

+                               st = 
db.getConnection().prepareStatement("SELECT originalName FROM indexes WHERE id 
= ?");

-               if ((privateKey != null) && (publicKey != null) && 
publicKey.startsWith("USK@")) {
-                       final String[] split = 
FreenetURIHelper.convertUSKtoSSK(publicKey).split("/");
-                       publicKey = split[0];
+                               st.setInt(1, id);
+                               ResultSet set = st.executeQuery();
+
+                               if (set.next()) {
+                                       realName = 
set.getString("originalName");
+                                       return realName;
+                               } else {
+                                       Logger.error(this, "Unable to get index 
real name: not found");
+                                       return null;
+                               }
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to get real index 
name: "+e.toString());
+                       }
                }

-               if ((publicKey != null) && publicKey.startsWith("USK@"))
-                       revision = FreenetURIHelper.getUSKRevision(publicKey);
+               return null;
        }

-       public String getPrivateKey() {
-               if ((privateKey == null) || Index.isDumbKey(privateKey))
-                       return null;
-               return privateKey;
-       }

-       public void setPrivateKey(final String key) {
-               if ((key != null) && !Index.isDumbKey(key))
-                       privateKey = key.trim();
-               else
-                       privateKey = null;
-       }
-
        public String toString() {
                return toString(true);
        }

        public String toString(boolean withRev) {
-               String toDisp;
+               if (displayName == null || rev < 0) {
+                       loadData();
+               }

-               if(displayName != null)
-                       toDisp = displayName;
-               else
-                       toDisp = realName;
+               if (withRev) {
+                       if (rev > 0 || privateKey == null)
+                               return displayName + " 
(r"+Integer.toString(rev)+")";
+                       else {
+                               if (rev > 0)
+                                       return displayName+" 
["+I18n.getMessage("thaw.plugin.index.nonInserted")+"]";
+                               else
+                                       return displayName;
+                       }
+               } else
+                       return displayName;

-               if (withRev && revision > 0)
-                       toDisp += " (r"+Integer.toString(revision)+")";
-
-               return toDisp;
        }

-       public boolean isLeaf() {
-               return true;
-       }


-       public void update(final java.util.Observable o, final Object p) {
+       public int insertOnFreenet(Observer o, IndexTree tree, FCPQueueManager 
queueManager) {
+               String privateKey = getPrivateKey();
+               String publicKey = getPublicKey();
+               int rev = getRevision();

-               if(o == sskGenerator) {
-                       sskGenerator.deleteObserver(this);
-                       publicKey = sskGenerator.getPublicKey();
-                       privateKey = sskGenerator.getPrivateKey();
-                       sskGenerator = null;
+               if (tree != null && tree.isIndexUpdating(this)) {
+                       Logger.notice(this, "A transfer is already running !");
+                       return 0;
+               }

-                       Logger.debug(this, "Index public key: " +publicKey);
-                       Logger.debug(this, "Index private key: "+privateKey);
-
-                       revision = 0;
-
-                       if (updateWhenKeyAreAvailable) {
-                               updateWhenKeyAreAvailable = false;
-                               update();
-                       }
-
-                       setChanged();
-                       notifyObservers();
-                       return;
+               if (!FreenetURIHelper.isAKey(publicKey)
+                   || !FreenetURIHelper.isAKey(privateKey)) { /* non 
modifiable */
+                       Logger.notice(this, "Tried to insert an index for which 
we don't have the private key ...");
+                       return 0;
                }

-               if(o == transfer) {
-                       if(transfer.isFinished() && transfer.isSuccessful()) {
-                               if(transfer instanceof FCPClientPut) {
+               String tmpdir = System.getProperty("java.io.tmpdir");

-                                       
((FCPClientPut)transfer).deleteObserver(this);
+               if (tmpdir == null)
+                       tmpdir = "";
+               else
+                       tmpdir = tmpdir + java.io.File.separator;

-                                       if (transfer.stop(queueManager))
-                                               queueManager.remove(transfer);
+               File targetFile = new java.io.File(tmpdir + getRealName() 
+".frdx");

-                                       this.setChanged();
-                                       this.notifyObservers();

-                                       return;
-                               }
+               Logger.info(this, "Generating index ...");

-                               if (transfer instanceof FCPClientGet) {
-                                       
((FCPClientGet)transfer).deleteObserver(this);
+               if (!generateXML(targetFile.getAbsolutePath()))
+                       return 0;

-                                       final int oldRevision = revision;
+               FCPClientPut put;

-                                       if (rewriteKey)
-                                               publicKey = 
transfer.getFileKey();
+               if(targetFile.exists()) {
+                       Logger.info(this, "Inserting new version");

-                                       revision = 
FreenetURIHelper.getUSKRevision(transfer.getFileKey());
+                       String publicSSK = 
FreenetURIHelper.convertUSKtoSSK(publicKey);
+                       publicSSK = 
FreenetURIHelper.changeSSKRevision(publicSSK, rev, 1);
+                       publicKey = FreenetURIHelper.convertSSKtoUSK(publicSSK);

-                                       Logger.info(this, "Most up-to-date key 
found: " + getPublicKey());
+                       rev++;

-                                       if (oldRevision < revision)
-                                               changed = true;
+                       put = new FCPClientPut(targetFile, 2, rev, realName, 
privateKey, 2, true, 0);
+                       put.setMetadata("ContentType", 
"application/x-freenet-index");

-                                       /* Reminder: These requests are 
non-peristent */
-                                       //if 
(this.transfer.stop(this.queueManager))
-                                       //      
this.queueManager.remove(this.transfer);
+                       if (tree != null)
+                               tree.addUpdatingIndex(this);

-                                       queueManager.remove(transfer);
+                       queueManager.addQueryToThePendingQueue(put);

-                                       if (transfer.getPath() == null) {
-                                               Logger.error(this, "No path 
?!");
-                                               return;
-                                       }
+                       put.addObserver(this);
+                       this.addObserver(o);

-                                       //if (changed)
-                                       loadXML(transfer.getPath());
+                       setPublicKey(publicKey, rev);

-                                       save();
+               } else {
+                       Logger.warning(this, "Index not generated !");
+                       return 0;
+               }

-                                       
indexBrowser.getUnknownIndexList().addLinks(this);

-                                       setChanged();
-                                       notifyObservers();
-                               }
-
-                       }
-
-                       if ((transfer != null) && transfer.isFinished() && 
!transfer.isSuccessful()) {
-                               Logger.info(this, "Unable to get new version of 
the index");
-
-                               this.setChanged();
-                               this.notifyObservers();
-                       }
-
-                       if (transfer != null && transfer.isFinished()) {
-                               Logger.info(this, "Removing file 
'"+transfer.getPath()+"'");
-                               final String path = transfer.getPath();
-                               if (path != null) {
-                                       final java.io.File fl = new 
java.io.File(path);
-                                       fl.delete();
-                               }
-                               else
-                                       Logger.error(this, "Unable to remove 
file !");
-                               setTransfer(null);
-                       }
-
-               }
-
-               if ((o instanceof thaw.plugins.index.File)
-                   || (o instanceof Link)) {
-                       this.setChanged();
-                       this.notifyObservers(o);
-               }
+               return 1;
        }

-
-       public boolean hasChanged() {
-               return changed;
+       public int downloadFromFreenet(Observer o, IndexTree tree, 
FCPQueueManager queueManager) {
+               return downloadFromFreenet(o, tree, queueManager, -1);
        }


-       public void setChanged(final boolean val) {
-               changed = val;
-       }
+       /**
+        * if true, when the transfer will finish, the index public key will be 
updated
+        */
+       private boolean rewriteKey = true;

+       private IndexTree indexTree = null;

-       public boolean isEmpty() {
-               if (fileList == null)
-                       loadFiles(null, true);
-               if (linkList == null)
-                       this.loadLinks(null, true);

-               if ((fileList.size() == 0) && (linkList.size() == 0))
-                       return true;
+       public int downloadFromFreenet(Observer o, IndexTree tree, 
FCPQueueManager queueManager, int specificRev) {
+               FCPClientGet clientGet;
+               String publicKey;

-               return false;
-       }
+               int rev = getRevision();

+               indexTree = tree;

-       ////// FILE LIST ////////
+               rewriteKey = true;

-       public void loadFiles(final String columnToSort, boolean asc) {
+               publicKey = getPublicKey();

-               fileList = new Vector();
+               if (tree != null && tree.isIndexUpdating(this)) {
+                       Logger.notice(this, "A transfer is already running !");
+                       return 0;
+               }

-               try {
-                       String query = "SELECT id, filename, publicKey, mime, 
size, localPath, category, indexParent FROM files WHERE indexParent = ?";
+               if (publicKey == null) {
+                       Logger.error(this, "No public key !! Can't get the 
index !");
+                       return 0;
+               }

-                       if(columnToSort != null) {
-                               query = query + "ORDER BY " + columnToSort;
+               Logger.info(this, "Getting lastest version ...");

-                               if(!asc)
-                                       query = query + " DESC";
-                       }
+               String key;

-                       final PreparedStatement st = 
db.getConnection().prepareStatement(query);
+               /* We will trust the node for the incrementation
+                  execept if a rev is specified */

-                       st.setInt(1, getId());

-                       if(st.execute()) {
-                               final ResultSet results = st.getResultSet();
+               if (specificRev >= 0) {
+                       key = FreenetURIHelper.convertUSKtoSSK(publicKey);
+                       key = FreenetURIHelper.changeSSKRevision(key, 
specificRev, 0);
+                       rewriteKey = false;
+               } else {
+                       key = publicKey;
+                       rewriteKey = true;
+               }

-                               while(results.next()) {
-                                       final thaw.plugins.index.File file = 
new thaw.plugins.index.File(db, results, this);
-                                       file.setTransfer(queueManager);
-                                       addFileToList(file);
-                               }
-                       }
+               Logger.info(this, "Updating index ...");
+               Logger.debug(this, "Key asked: "+key);


-               } catch(final java.sql.SQLException e) {
-                       Logger.error(this, "Unable to get the file list for 
index: '"+toString()+"' because: "+e.toString());
-               }
+               clientGet = new FCPClientGet(key, 2, 2, false, -1,
+                                            
System.getProperty("java.io.tmpdir"));

-               setChanged(false); /* java.util.Index */
-               setChanged(); /* java.util.Observer */
-               notifyObservers();
-       }
+               /*
+                * These requests are usually quite fast, and don't consume too 
much
+                * of bandwith / CPU. So we can skip the queue and start 
immediatly
+                * (and like this, they won't appear in the queue)
+                */
+               clientGet.start(queueManager);

-       /**
-        * Returns a *copy* of da vector.
-        */
-       public Vector getFileList() {
-               final Vector newList = new Vector();
+               if (tree != null)
+                       tree.addUpdatingIndex(this);

-               if (fileList == null)
-                       return newList;
+               clientGet.addObserver(this);

-               for(final Iterator it = fileList.iterator();
-                   it.hasNext();) {
-                       newList.add(it.next());
-               }
+               this.addObserver(o);

-               return newList;
+               return 1;
        }

-       public thaw.plugins.index.File getFile(final int index) {
-               return (thaw.plugins.index.File)fileList.get(index);
-       }

-       public int getFilePosition(final thaw.plugins.index.File fileA) {
-               int pos = fileList.indexOf(fileA);

-               if (fileA.getPublicKey() == null)
-                       return -1;
+       public void update(Observable o, Object param) {
+               if (o instanceof FCPClientGet) {
+                       FCPClientGet get = (FCPClientGet)o;

-               if (pos < 0) {
-                       /* Manual research */
-                       pos = 0;
-                       for(final Iterator it = fileList.iterator();
-                           it.hasNext();) {
-                               final thaw.plugins.index.File fileB = 
(thaw.plugins.index.File)it.next();
+                       String key = get.getFileKey();

-                               if ((fileB.getPublicKey() != null)
-                                   && 
fileB.getPublicKey().equals(fileA.getPublicKey()))
-                                       return pos;
-                               pos++;
+                       int oldRev = rev;
+                       int newRev = FreenetURIHelper.getUSKRevision(key);

+                       if (rewriteKey) {
+                               setPublicKey(key, newRev);
                        }
-               }

-               return -1;
-       }
+                       if (oldRev < newRev)
+                               setHasChangedFlag(true);

+                       if (get.isFinished() && get.isSuccessful()) {
+                               String path = get.getPath();

-       public void unloadFiles() {
-               if (fileList != null) {
-                       for (final Iterator it  = fileList.iterator();
-                            it.hasNext();)
-                               {
-                                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
-                                       file.deleteObserver(this);
-                               }
+                               if (path != null) {
+                                       loadXML(path);
+                               } else
+                                       Logger.error(this, "No path specified 
in transfer ?!");
+                       }
                }

-               fileList = null;
-       }

+               /* nothing special to do if it is an insert */
+               /* TODO : check if it's successful, else merge if it's due to a 
collision */

-       /**
-        * Note for myself: For external use only ! (file will be inserted in 
the database etc)
-        */
-       public void addFile(final thaw.plugins.index.File file) {
-               file.setParent(this);

-               if (!file.isInTheDatabase()) {
-                       file.insert();
+               if (o instanceof FCPTransferQuery) {
+                       FCPTransferQuery transfer = (FCPTransferQuery)o;

-                       addFileToList(file);
+                       if (transfer.isFinished()) {
+                               String path = transfer.getPath();

-                       this.setChanged();
-                       this.notifyObservers(file);
-               }
-               else
-                       Logger.notice(this, "File already in the database for 
this index");
-       }
+                               final java.io.File fl = new java.io.File(path);
+                               fl.delete();

+                               ((Observable)transfer).deleteObserver(this);
+                               if (indexTree != null)
+                                       indexTree.removeUpdatingIndex(this);

-       /**
-        * Won't notify
-        */
-       protected void addFileToList(final thaw.plugins.index.File file) {
-               if (fileList == null)
-                       loadFiles(null, true);
-               file.addObserver(this);
-               fileList.add(file);
-       }
-
-
-       public void removeFile(final thaw.plugins.index.File file) {
-               file.delete();
-
-               if(fileList != null) {
-                       fileList.remove(file);
-
-                       this.setChanged();
-                       this.notifyObservers(file);
+                               setChanged();
+                               notifyObservers();
+                       }
                }
-       }

-       /**
-        * Do the update all the files in the database.
-        */
-       public void updateFileList() {
-               for(final Iterator it = fileList.iterator(); it.hasNext();) {
-                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
-                       file.update();
-               }
        }


-       //// LINKS ////
+       ////// FILE LIST ////////

-       public void addLink(final Link link) {
-               link.setParent(this);
+       public Vector getFileList(String columnToSort, boolean asc) {
+               synchronized(db.dbLock) {

-               if (!link.isInTheDatabase()) {
-                       link.insert();
+                       try {
+                               Vector files = new Vector();

-                       addLinkToList(link);
+                               PreparedStatement st;

-                       setChanged();
-                       notifyObservers(link);
-               }
-               else
-                       Logger.notice(this, "Link already in the database for 
this index");
+                               if (columnToSort == null) {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, filename, publicKey, localPath, 
mime, size "+
+                                                                               
 "FROM files WHERE indexParent = ?");
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, filename, publicKey, localPath, 
mime, size "+
+                                                                               
 "FROM files WHERE indexParent = ? ORDER by "+
+                                                                               
 columnToSort + (asc == true ? "" : " DESC"));
+                               }

-       }
+                               st.setInt(1, id);

-       protected void addLinkToList(final Link link) {
-               if (linkList == null)
-                       this.loadLinks(null, true);
+                               ResultSet rs = st.executeQuery();

-               linkList.add(link);
-       }
+                               while(rs.next()) {
+                                       int file_id = rs.getInt("id");
+                                       String filename = 
rs.getString("filename");
+                                       String file_publicKey = 
rs.getString("publicKey");
+                                       String lp = rs.getString("localPath");
+                                       java.io.File localPath = (lp == null ? 
null : new java.io.File(lp));
+                                       String mime = rs.getString("mime");
+                                       long size = rs.getLong("size");

-       public void removeLink(final Link link) {
-               link.delete();
+                                       thaw.plugins.index.File file =
+                                               new thaw.plugins.index.File(db, 
file_id, filename, file_publicKey,
+                                                                           
localPath, mime, size, id);
+                                       files.add(file);
+                               }

-               if (linkList != null) {
-                       linkList.remove(link);
-                       this.setChanged();
-                       this.notifyObservers(link);
-               }
+                               return files;

-       }
-
-       /**
-        * Update all the links in the database.
-        */
-       public void updateLinkList() {
-               for(final Iterator it = linkList.iterator(); it.hasNext();) {
-                       final Link link = (Link)it.next();
-                       link.update();
+                       } catch(SQLException e) {
+                               Logger.error(this, "SQLException while getting 
file list: "+e.toString());
+                       }
                }
+               return null;
        }

-       public void loadLinks(final String columnToSort, boolean asc)
-       {
-               linkList = new Vector();

-               try {
-                       String query = "SELECT id, publicKey, mark, comment, 
indexTarget FROM links WHERE indexParent = ?";
+       //// LINKS ////

-                       if(columnToSort != null) {
-                               query = query + "ORDER BY " + columnToSort;
+       public Vector getLinkList(String columnToSort, boolean asc) {
+               synchronized(db.dbLock) {

-                               if(!asc)
-                                       query = query + " DESC";
-                       }
+                       try {
+                               Vector links = new Vector();

-                       final PreparedStatement st = 
db.getConnection().prepareStatement(query);
+                               PreparedStatement st;

-                       st.setInt(1, getId());
+                               st = 
db.getConnection().prepareStatement("SELECT id, publicKey FROM links WHERE 
indexParent = ?");

-                       if(st.execute()) {
-                               final ResultSet results = st.getResultSet();
+                               st.setInt(1, id);

-                               while(results.next()) {
-                                       try {
-                                               final Link link = new Link(db, 
results, this);
-                                               addLinkToList(link);
-                                       } catch(final Exception e) {
-                                               Logger.warning(this, "Unable to 
add index '"+publicKey+"' to the list because: "+e.toString());
-                                       }
+                               ResultSet res = st.executeQuery();
+
+                               while(res.next()) {
+                                       Link l = new Link(db, res.getInt("id"), 
res.getString("publicKey"), id);
+                                       links.add(l);
                                }
-                       }

+                               return links;

-               } catch(final java.sql.SQLException e) {
-                       Logger.error(this, "Unable to get the link list for 
index: '"+toString()+"' because: "+e.toString());
+                       } catch(SQLException e) {
+                               Logger.error(this, "SQLException while getting 
link list: "+e.toString());
+                       }
                }

-               setChanged(false); /* Index */
-               setChanged();      /* java.util.Observable */
-               notifyObservers();
-
+               return null;
        }

-       /* Returns a copy ! */
-       public Vector getLinkList()
-       {
-               final Vector newList = new Vector();
-
-               if (linkList == null)
-                       return newList;
-
-               for(final Iterator it = linkList.iterator();
-                   it.hasNext();) {
-                       newList.add(it.next());
+       //// XML ////
+       public boolean generateXML(String path) {
+               try {
+                       generateXML(new FileOutputStream(new File(path)));
+                       return true;
+               } catch(java.io.FileNotFoundException e) {
+                       Logger.error(this, "File not found exception ?!");
                }
-
-               return newList;
+               return false;
        }

-       public Link getLink(final int index)
-       {
-               return (Link)linkList.get(index);
-       }
+       public void generateXML(final OutputStream out) {
+               StreamResult streamResult;

-       public void unloadLinks()
-       {
-               linkList = null;
-       }
+               streamResult = new StreamResult(out);

-
-       //// XML ////
-
-       public void generateXML(final OutputStream out) {
-               final StreamResult streamResult = new StreamResult(out);
-
                Document xmlDoc;

                final DocumentBuilderFactory xmlFactory = 
DocumentBuilderFactory.newInstance();
@@ -997,9 +835,7 @@

                final Element rootEl = xmlDoc.getDocumentElement();

-               rootEl.appendChild(getXMLHeader(xmlDoc));
-               rootEl.appendChild(getXMLLinks(xmlDoc));
-               rootEl.appendChild(getXMLFileList(xmlDoc));
+               fillInRootElement(rootEl, xmlDoc);

                /* Serialization */
                final DOMSource domSource = new DOMSource(xmlDoc);
@@ -1026,46 +862,62 @@
                }
        }

+       public boolean fillInRootElement(Element rootEl, Document xmlDoc) {
+               rootEl.appendChild(getXMLHeader(xmlDoc));
+               rootEl.appendChild(getXMLLinks(xmlDoc));
+               rootEl.appendChild(getXMLFileList(xmlDoc));
+
+               return true;
+       }
+
        public Element getXMLHeader(final Document xmlDoc) {
                final Element header = xmlDoc.createElement("header");

                final Element title = xmlDoc.createElement("title");
-               final Text titleText = xmlDoc.createTextNode(displayName);
+               final Text titleText = xmlDoc.createTextNode(toString(false));
                title.appendChild(titleText);

-               final Element owner = xmlDoc.createElement("owner");
-               Text ownerText;
+               header.appendChild(title);

-               if (author == null)
-                       ownerText = xmlDoc.createTextNode("Another anonymous");
-               else
-                       ownerText = xmlDoc.createTextNode(author);
+               if (getPublishPrivateKey() && getPrivateKey() != null) {
+                       final Element privateKeyEl = 
xmlDoc.createElement("privateKey");
+                       final Text privateKeyText = 
xmlDoc.createTextNode(getPrivateKey());
+                       privateKeyEl.appendChild(privateKeyText);

-               owner.appendChild(ownerText);
+                       header.appendChild(privateKeyEl);
+               }

-               header.appendChild(title);
-               header.appendChild(owner);

+               /* TODO : Author */
+
                return header;
        }

        public Element getXMLLinks(final Document xmlDoc) {
                final Element links = xmlDoc.createElement("indexes");
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

-               if (linkList == null) {
-                       this.loadLinks(null, true);
-               }
+                               st = 
db.getConnection().prepareStatement("SELECT publicKey FROM links WHERE 
indexParent = ?");
+                               st.setInt(1, id);

-               for (final Iterator it = getLinkList().iterator();
-                    it.hasNext();) {
-                       final Link link = (Link)it.next();
+                               ResultSet set = st.executeQuery();

-                       final Element xmlLink = link.getXML(xmlDoc);
+                               while (set.next()) {
+                                       final Element xmlLink = 
xmlDoc.createElement("index");

-                       if (xmlLink != null)
-                               links.appendChild(xmlLink);
-                       else
-                               Logger.warning(this, "Unable to get XML for the 
link '"+link.getIndexName()+"' => Gruick da link");
+                                       xmlLink.setAttribute("key", 
set.getString("publicKey"));
+
+                                       if (xmlLink != null)
+                                               links.appendChild(xmlLink);
+                                       else
+                                               Logger.warning(this, "Unable to 
get XML for a link => Gruick da link");
+
+                               }
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while getting link 
list for XML : "+e.toString());
+                       }
                }

                return links;
@@ -1074,34 +926,74 @@
        public Element getXMLFileList(final Document xmlDoc) {
                final Element files = xmlDoc.createElement("files");

-               if(fileList == null) {
-                       loadFiles(null, true);
-               }
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

-               for(final Iterator it = getFileList().iterator();
-                   it.hasNext();) {
-                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                               st = 
db.getConnection().prepareStatement("SELECT id, filename, publicKey, size, mime 
"+
+                                                                        "FROM 
files "+
+                                                                        "WHERE 
indexParent = ?");

-                       final Element xmlFile = file.getXML(xmlDoc);
+                               st.setInt(1, id);

-                       if(xmlFile != null)
-                               files.appendChild(xmlFile);
-                       else
-                               Logger.warning(this, "Public key wasn't 
generated ! Not added to the index !");
+                               ResultSet set = st.executeQuery();
+
+                               while(set.next()) {
+                                       String pubKey = 
set.getString("publicKey");
+
+                                       if (pubKey == null)
+                                               continue;
+
+                                       pubKey = pubKey.trim();
+
+                                       if (!FreenetURIHelper.isAKey(pubKey)) {
+                                               Logger.notice(this, "One of the 
file key wasn't generated => not added");
+                                               continue;
+                                       }
+
+                                       final Element xmlFile = 
xmlDoc.createElement("file");
+
+                                       xmlFile.setAttribute("id", 
set.getString("id"));
+                                       xmlFile.setAttribute("key", pubKey);
+                                       xmlFile.setAttribute("size", 
set.getString("size"));
+                                       if (set.getString("mime") == null)
+                                               xmlFile.setAttribute("mime", 
DefaultMIMETypes.guessMIMEType(set.getString("filename")));
+                                       else
+                                               xmlFile.setAttribute("mime", 
set.getString("mime"));
+
+                                       if(xmlFile != null)
+                                               files.appendChild(xmlFile);
+                                       else
+                                               Logger.warning(this, "Public 
key wasn't generated ! Not added to the index !");
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while getting file 
list for XML : "+e.toString());
+                       }
                }

                return files;
        }

+
+
        public void loadXML(final String filePath) {
+               loadXML(filePath, true);
+       }
+
+
+       /**
+        * @param clean if set to false, will do a merge
+        */
+       public void loadXML(final String filePath, boolean clean) {
                try {
-                       loadXML(new FileInputStream(filePath));
+                       loadXML(new FileInputStream(filePath), clean);
                } catch(final java.io.FileNotFoundException e) {
                        Logger.error(this, "Unable to load XML: 
FileNotFoundException ('"+filePath+"') ! : "+e.toString());
                }
        }

-       public synchronized void loadXML(final java.io.InputStream input) {
+       public synchronized void loadXML(final java.io.InputStream input, 
boolean clean) {
                final DocumentBuilderFactory xmlFactory = 
DocumentBuilderFactory.newInstance();
                DocumentBuilder xmlBuilder;

@@ -1128,30 +1020,39 @@

                final Element rootEl = xmlDoc.getDocumentElement();

-               loadXML(rootEl);
+               Logger.info(this, "Extracting informations from index ...");
+               loadXML(rootEl, clean);
+               Logger.info(this, "Extraction done");
        }

-       public void loadXML(Element rootEl) {
+       public void loadXML(Element rootEl, boolean clean) {
                loadHeader(rootEl);
-               loadLinks(rootEl);
-               loadFileList(rootEl);
+               loadLinks(rootEl, clean);
+               loadFileList(rootEl, clean);
        }


        public void loadHeader(final Element rootEl) {
                final Element header = 
(Element)rootEl.getElementsByTagName("header").item(0);

-               if (header == null)
-                       return;
+               if (publicKey == null)
+                       loadData();

-               realName = getHeaderElement(header, "title");
-               author = getHeaderElement(header, "owner");
+               String pKey = getHeaderElement(header, "privateKey");
+               if (pKey != null) {
+                       if (privateKey == null || 
privateKey.trim().equals(pKey.trim())) {
+                               /* the public key was published, we will have 
to do the same later */
+                               setPublishPrivateKey(true);
+                       }
+                       else
+                               setPublishPrivateKey(false);

-               if (author == null)
-                       author = "Another anonymous";
+                       if (privateKey == null)
+                               setPrivateKey(pKey.trim());
+               }
        }

-       public String getHeaderElement(final Element header, final String name) 
{
+       protected String getHeaderElement(final Element header, final String 
name) {
                try {
                        if (header == null)
                                return null;
@@ -1178,52 +1079,219 @@
                }
        }

-       public void loadLinks(final Element rootEl) {
-               purgeLinkList();
-
+       public void loadLinks(final Element rootEl, boolean clean) {
                final Element links = 
(Element)rootEl.getElementsByTagName("indexes").item(0);

-               if (links == null)
+               if (links == null) {
+                       Logger.notice(this, "No links in index !");
                        return;
+               }

                final NodeList list = links.getChildNodes();

-               for(int i = 0; i < list.getLength() ; i++) {
-                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
-                               final Element e = (Element)list.item(i);
+               PreparedStatement updateSt = null;
+               PreparedStatement insertSt = null;
+               int nextId;

-                               final Link link = new Link(db, e, this);
-                               addLink(link);
+               synchronized(db.dbLock) {
+                       try {
+                               updateSt =
+                                       
db.getConnection().prepareStatement("UPDATE links "+
+                                                                           
"SET publicKey = ?, "+
+                                                                           
"toDelete = FALSE "+
+                                                                           
"WHERE indexParent = ? "+
+                                                                           
"AND LOWER(publicKey) LIKE ?");
+                               insertSt =
+                                       
db.getConnection().prepareStatement("INSERT INTO links "
+                                                                           + 
"(id, publicKey, mark, comment, indexParent, indexTarget) "
+                                                                           + 
"VALUES (?, ?, 0, ?, ?, NULL)");
+                               if ((nextId = DatabaseManager.getNextId(db, 
"links")) < 0)
+                                       return;
+
+                               PreparedStatement st =
+                                       
db.getConnection().prepareStatement("UPDATE links "+
+                                                                           
"SET toDelete = TRUE "+
+                                                                           
"WHERE indexParent = ?");
+                               st.setInt(1, id);
+                               st.execute();
+                       } catch(SQLException exc) {
+                               Logger.error(this, "Unable to prepare statement 
because: "+exc.toString());
+                               return;
                        }
+
+                       if (list.getLength() < 0) {
+                               Logger.notice (this, "No link ?!");
+                       }
+
+                       for(int i = 0; i < list.getLength() ; i++) {
+                               if(list.item(i).getNodeType() == 
Node.ELEMENT_NODE) {
+                                       final Element e = (Element)list.item(i);
+
+                                       String key = e.getAttribute("key");
+
+                                       if (key == null) {
+                                               Logger.notice(this, "No key in 
this link ?!");
+                                               continue;
+                                       }
+
+                                       key = key.trim();
+
+                                       try {
+                                               updateSt.setString(1, key);
+                                               updateSt.setInt(2, id);
+                                               updateSt.setString(3, key);
+
+                                               if (updateSt.executeUpdate() <= 
0) {
+
+                                                       insertSt.setInt(1, 
nextId);
+                                                       insertSt.setString(2, 
key);
+                                                       insertSt.setString(3, 
"No comment"); /* comment not used at the moment */
+                                                       insertSt.setInt(4, id);
+
+                                                       insertSt.execute();
+                                                       nextId++;
+                                               }
+
+                                       } catch(SQLException exc) {
+                                               Logger.error(this, "Unable to 
add link because: "+exc.toString());
+                                       }
+                               }
+                       } /* for() */
+
+                       if (clean) {
+                               try {
+                                       PreparedStatement st;
+
+                                       st = 
db.getConnection().prepareStatement("DELETE FROM links "+
+                                                                               
         "WHERE toDelete = TRUE "+
+                                                                               
         "AND indexParent = ?");
+                                       st.setInt(1, id);
+                                       st.execute();
+                               } catch(SQLException exc) {
+                                       Logger.error(this, "error while clean 
index (links) : "+exc.toString());
+                               }
+
+                       }
                }

-               setChanged();
-               notifyObservers();
        }

-       public void loadFileList(final Element rootEl) {
-               purgeFileList();
-
+       public void loadFileList(final Element rootEl, boolean clean) {
                final Element filesEl = 
(Element)rootEl.getElementsByTagName("files").item(0);

-               if (filesEl == null)
+               if (filesEl == null) {
+                       Logger.notice(this, "No file in the index !");
                        return;
+               }

-               final NodeList list = filesEl.getChildNodes();
+               PreparedStatement updateSt = null;
+               PreparedStatement insertSt = null;
+               int nextId;

-               for(int i = 0; i < list.getLength() ; i++) {
-                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
-                               final Element e = (Element)list.item(i);
+               synchronized(db.dbLock) {
+                       try {
+                               updateSt =
+                                       
db.getConnection().prepareStatement("UPDATE files "+
+                                                                           
"SET filename = ?, "+
+                                                                           
"publicKey = ?, " +
+                                                                           
"mime = ?, "+
+                                                                           
"size = ?, "+
+                                                                           
"toDelete = FALSE "+
+                                                                           
"WHERE indexParent = ? "+
+                                                                           
"AND LOWER(publicKey) LIKE ?");
+                               insertSt =
+                                       
db.getConnection().prepareStatement("INSERT INTO files "
+                                                                           + 
"(id, filename, publicKey, localPath, mime, size, category, indexParent) "
+                                                                           + 
"VALUES (?, ?, ?, NULL, ?, ?, NULL, ?)");
+                               if ((nextId = DatabaseManager.getNextId(db, 
"files")) < 0)
+                                       return;

-                               final thaw.plugins.index.File file = new 
thaw.plugins.index.File(db, e, this);
-                               addFile(file);
+                               PreparedStatement st;

+                               st = 
db.getConnection().prepareStatement("UPDATE files "+
+                                                                        "SET 
toDelete = TRUE "+
+                                                                        "WHERE 
indexParent = ?");
+                               st.setInt(1, id);
+                               st.execute();
+                       } catch(SQLException exc) {
+                               Logger.error(this, "Unable to prepare statement 
because: "+exc.toString());
+                               return;
                        }
+
+                       final NodeList list = filesEl.getChildNodes();
+
+                       if (list.getLength() < 0) {
+                               Logger.notice(this, "No files?!");
+                       }
+
+                       for(int i = 0; i < list.getLength() ; i++) {
+                               if(list.item(i).getNodeType() == 
Node.ELEMENT_NODE) {
+
+                                       final Element e = (Element)list.item(i);
+
+                                       String key = e.getAttribute("key");
+
+                                       if (key == null)
+                                               continue;
+
+                                       key = key.trim();
+
+                                       long size = 0;
+
+                                       if (e.getAttribute("size") != null)
+                                               size = 
Long.parseLong(e.getAttribute("size"));
+                                       String mime = e.getAttribute("mime");
+                                       String filename = 
FreenetURIHelper.getFilenameFromKey(key);
+
+                                       try {
+                                               updateSt.setString(1, filename);
+                                               updateSt.setString(2, key);
+                                               updateSt.setString(3, mime);
+                                               updateSt.setLong(4, size);
+                                               updateSt.setInt(5, id);
+                                               updateSt.setString(6, 
FreenetURIHelper.getComparablePart(key)+"%");
+
+                                               int rs = 
updateSt.executeUpdate();
+
+                                               if (rs <= 0) {
+                                                       insertSt.setInt(1, 
nextId);
+                                                       insertSt.setString(2, 
filename);
+                                                       insertSt.setString(3, 
key);
+                                                       insertSt.setString(4, 
mime);
+                                                       insertSt.setLong(5, 
size);
+                                                       insertSt.setInt(6, id);
+
+                                                       nextId++;
+
+                                                       insertSt.execute();
+                                               }
+                                       } catch(SQLException exc) {
+                                               Logger.error(this, "error while 
adding file: "+exc.toString());
+                                               Logger.error(this, "Next id : 
"+Integer.toString(nextId));
+                                               exc.printStackTrace();
+                                               return;
+                                       }
+
+                               }
+                       } /* for each file in the XML */
+
+
+                       if (clean) {
+                               try {
+                                       PreparedStatement st;
+
+                                       st = 
db.getConnection().prepareStatement("DELETE FROM files "+
+                                                                               
 "WHERE toDelete = TRUE "+
+                                                                               
 "AND indexParent = ?");
+                                       st.setInt(1, id);
+                                       st.execute();
+                               } catch(SQLException exc) {
+                                       Logger.error(this, "error while clean 
index (files) : "+exc.toString());
+                               }
+                       }
                }

-               this.setChanged();
-               this.notifyObservers();
-       }
+       } /* loadFileList() */


        static String getNameFromKey(final String key) {
@@ -1234,6 +1302,7 @@
                if (name == null)
                        return null;

+               /* quick and dirty */
                name = name.replaceAll(".xml", "");
                name = name.replaceAll(".frdx", "");

@@ -1241,26 +1310,11 @@
        }


-       public Vector getIndexIds() {
-               final Vector ids = new Vector();
-               ids.add(new Integer(getId()));
-               return ids;
-       }
-
-       public Vector getIndexes() {
-               final Vector idx = new Vector();
-               idx.add(this);
-               return idx;
-       }
-
        public boolean isModifiable() {
-               return (privateKey != null);
-       }
+               if (getPrivateKey() != null)
+                       return true;

-       public boolean isInIndex(final thaw.plugins.index.File file) {
-               if (fileList == null)
-                       loadFiles(null, true);
-               return fileList.contains(file);
+               return false;
        }


@@ -1270,23 +1324,72 @@
                        return false;
                }

-               try {
-                       PreparedStatement st;
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

-                       st = db.getConnection().prepareStatement("SELECT 
publicKey from indexes WHERE publicKey LIKE ?");
+                               st = 
db.getConnection().prepareStatement("SELECT publicKey from indexes WHERE 
LOWER(publicKey) LIKE ? LIMIT 1");

-                       st.setString(1, "%"+key.substring(3, 
40).replaceAll("%","\\%") +"%");
+                               st.setString(1, 
FreenetURIHelper.getComparablePart(key) +"%");

-                       if(st.execute()) {
-                               final ResultSet result = st.getResultSet();
-                               if ((result != null) && result.next())
+                               ResultSet res = st.executeQuery();
+
+                               if (res.next()) {
                                        return true;
+                               }
+
+                       } catch(final SQLException e) {
+                               Logger.error(new Index(), "isAlreadyKnown: 
Unable to check if link '"+key+"' point to a know index because: 
"+e.toString());
                        }
+               }

-               } catch(final SQLException e) {
-                       Logger.error(new Index(), "isAlreadyKnown: Unable to 
check if link '"+key+"' point to a know index because: "+e.toString());
+               return false;
+       }
+
+
+       public void forceHasChangedReload() {
+               /* Do nothing here */
+       }
+
+
+       public boolean hasChanged() {
+               if (publicKey == null) {
+                       loadData();
                }

+               return hasChanged;
+       }
+
+
+       public boolean setHasChangedFlagInMem(boolean flag) {
+               hasChanged = flag;
+               return true;
+       }
+
+
+       /**
+        * @return true if a change was done
+        */
+       public boolean setHasChangedFlag(boolean flag) {
+               setHasChangedFlagInMem(flag);
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("UPDATE indexes SET newRev = ? "+
+                                                                        "WHERE 
id = ?");
+
+                               st.setBoolean(1, flag);
+                               st.setInt(2, id);
+                               if (st.executeUpdate() > 0)
+                                       return true;
+                               return false;
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to change 
'hasChanged' flag because: "+e.toString());
+                       }
+               }
+
                return false;
        }

@@ -1294,26 +1397,30 @@
        public Element do_export(Document xmlDoc, boolean withContent) {
                Element e = xmlDoc.createElement("fullIndex");

-               e.setAttribute("displayName", displayName);
+               e.setAttribute("displayName", toString(false));
                e.setAttribute("publicKey", getPublicKey());
                if (getPrivateKey() != null)
                        e.setAttribute("privateKey", getPrivateKey());

                if (withContent) {
-                       e.appendChild(getXMLHeader(xmlDoc));
-                       e.appendChild(getXMLLinks(xmlDoc));
-                       e.appendChild(getXMLFileList(xmlDoc));
+                       fillInRootElement(e, xmlDoc);
                }

                return e;
        }

-       /**
-        * will call create() !!
-        */
-       public void do_import(Element e) {
-               String dn;
-               loadXML(e);
+
+       public void do_import(IndexBrowserPanel indexBrowser, Element e) {
+               loadXML(e, true);
        }

+
+       public boolean equals(Object o) {
+               if (o == null || !(o instanceof Index))
+                       return false;
+
+               if (((Index)o).getId() == getId())
+                       return true;
+               return false;
+       }
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java       
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java       
2007-01-25 07:03:17 UTC (rev 11613)
@@ -44,8 +44,8 @@

                unknownList = new UnknownIndexList(queueManager, this);

-               indexTree = new 
IndexTree(I18n.getMessage("thaw.plugin.index.indexes"), false, queueManager, 
this, config);
-               indexTree.makeFlatList();
+               indexTree = new 
IndexTree(I18n.getMessage("thaw.plugin.index.indexes"),
+                                         false, queueManager, this, config);

                leftSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                                           indexTree.getPanel(),
@@ -128,8 +128,11 @@
                return globalPanel;
        }

+       public void stopAllThreads() {
+               tables.stopRefresh();
+       }
+
        public void saveState() {
-               indexTree.save();
                config.setValue("indexBrowserPanelSplitPosition", 
Integer.toString(split.getDividerLocation()));
                int splitLocation;

@@ -164,7 +167,7 @@
                        return;
                }

-               final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+               final IndexTreeNode node = 
(IndexTreeNode)(path.getLastPathComponent());

                if(node == null) {
                        Logger.notice(this, "Node null ?");
@@ -199,4 +202,5 @@
                }
        }

+
 }

Deleted: trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java   2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java   2007-01-25 
07:03:17 UTC (rev 11613)
@@ -1,614 +0,0 @@
-package thaw.plugins.index;
-
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Types;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Vector;
-
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.MutableTreeNode;
-import javax.swing.tree.TreeNode;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import thaw.core.Logger;
-import thaw.fcp.FCPQueueManager;
-import thaw.plugins.Hsqldb;
-
-public class IndexCategory extends DefaultMutableTreeNode implements 
IndexTreeNode {
-
-       private static final long serialVersionUID = 1L;
-       private int id;
-       private IndexCategory parent;
-       private String name;
-
-       private Hsqldb db;
-       private FCPQueueManager queueManager;
-       private IndexBrowserPanel indexBrowser;
-
-       public IndexCategory(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser,
-                            final int id, final IndexCategory parent,
-                            final String name) {
-               super(name, true);
-
-               this.indexBrowser = indexBrowser;
-               this.id = id;
-               this.name = name;
-               this.parent = parent;
-
-               this.db = indexBrowser.getDb();
-
-               this.queueManager = queueManager;
-
-               setUserObject(this);
-
-       }
-
-       public void setParent(final IndexCategory parent) {
-               this.parent = parent;
-       }
-
-       public DefaultMutableTreeNode getTreeNode() {
-               return this;
-       }
-
-       /**
-        * Insert the category into the database.
-        */
-       public boolean create() {
-               try {
-                       /* Rahh ! Hsqldb doesn't support getGeneratedKeys() ! 
8/ */
-
-                       final Connection c = db.getConnection();
-                       PreparedStatement st;
-
-                       st = c.prepareStatement("SELECT id FROM indexCategories 
ORDER BY id DESC LIMIT 1");
-                       st.execute();
-
-                       try {
-                               final ResultSet key = st.getResultSet();
-                               key.next();
-                               id = key.getInt(1) + 1;
-                       } catch(final SQLException e) {
-                               id = 0;
-                       }
-
-                       st = c.prepareStatement("INSERT INTO indexCategories 
(id, name, positionInTree, parent, modifiableIndexes) "+
-                                                                 "VALUES (?, 
?,?,?, true)");
-
-                       st.setInt(1, id);
-                       st.setString(2, name);
-                       st.setInt(3, 0);
-
-
-                       if(parent.getId() >= 0)
-                               st.setInt(4, parent.getId());
-                       else
-                               st.setNull(4, Types.INTEGER);
-
-                       st.execute();
-
-                       return true;
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to insert the new index 
category in the db, because: "+e.toString());
-
-                       return false;
-               }
-       }
-
-       public void delete() {
-               if (id < 0) /* Operation not allowed */
-                       return;
-
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode child = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       child.delete();
-               }
-
-               unloadChildren();
-
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("DELETE 
FROM indexCategories WHERE id = ?");
-                       st.setInt(1, id);
-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to delete the index category 
'"+name+"', because: "+e.toString());
-               }
-       }
-
-       public void rename(final String name) {
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("UPDATE 
indexCategories SET name = ? WHERE id = ?");
-
-                       st.setString(1, name);
-                       st.setInt(2, id);
-
-                       st.execute();
-
-                       this.name = name;
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to rename the index category 
'"+this.name+"' in '"+name+"', because: "+e.toString());
-               }
-       }
-
-       public String getPublicKey() {
-               String result = "";
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       result = result + node.getPublicKey();
-
-                       if (it.hasNext())
-                               result = result + "\n";
-               }
-
-               return result;
-       }
-
-       public String getPrivateKey() {
-               String result = "";
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       result = result + node.getPrivateKey();
-
-                       if (it.hasNext())
-                               result = result + "\n";
-               }
-
-               return result;
-       }
-
-       public void addObserver(final java.util.Observer o) {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       node.addObserver(o);
-               }
-       }
-
-       public void update() {
-               for (final Enumeration e = children() ; e.hasMoreElements() ;) {
-                       
((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement()).getUserObject()).update();
-               }
-       }
-
-       public void updateFromFreenet(final int rev) {
-               for (final Enumeration e = children() ; e.hasMoreElements() ;) {
-                       
((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement()).getUserObject()).updateFromFreenet(rev);
-               }
-       }
-
-       public boolean isUpdating() {
-               for (final Enumeration e = children() ; e.hasMoreElements() ;) {
-                       
if(((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement())).isUpdating())
-                               return true;
-               }
-
-               return false;
-       }
-
-       public void save() {
-               saveThis();
-
-               for (final Enumeration e = children() ; e.hasMoreElements() ;) {
-                       
((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement()).getUserObject()).save();
-               }
-       }
-
-
-       public void saveThis() {
-               if(getId() < 0)
-                       return;
-
-               try {
-                       final Connection c = db.getConnection();
-                       final PreparedStatement st = c.prepareStatement("UPDATE 
indexCategories SET name = ?, positionInTree = ?, parent = ? WHERE id = ?");
-
-                       st.setString(1, name);
-                       st.setInt(2, getParent().getIndex(this)); /* Index = 
position here */
-
-                       if( ((IndexTreeNode)getParent()).getId() < 0)
-                               st.setNull(3, Types.INTEGER);
-                       else
-                               st.setInt(3, 
((IndexTreeNode)getParent()).getId());
-
-                       st.setInt(4, getId());
-
-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to save index category state 
'"+toString()+"' because : "+e.toString());
-               }
-       }
-
-       public int getId() {
-               return id;
-       }
-
-       public int getChildNumber() {
-               if (children == null)
-                       children = loadChildren();
-
-               if (children == null)
-                       return 0;
-
-               return children.size();
-       }
-
-       public Vector loadChildren() {
-               final Vector children = new Vector();
-
-               Logger.debug(this, "loadChildren()");
-
-               loadChildCategories(children);
-               loadChildIndexes(children);
-
-               cleanChildList(children);
-
-               Logger.debug(this, "Children: "+children.size());
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext(); ) {
-                       add((MutableTreeNode)it.next());
-               }
-
-               return children;
-       }
-
-       public void unloadChildren() {
-               children = null;
-       }
-
-
-       public void loadChildIndexes(final Vector children) {
-
-               ResultSet result;
-
-               String query;
-
-               query = "SELECT id, originalName, displayName, publicKey, 
privateKey, author, positionInTree, revision FROM indexes";
-
-               if(id < 0)
-                       query = query + " WHERE parent IS NULL";
-               else
-                       query = query + " WHERE parent = "+Integer.toString(id);
-
-               query = query + " ORDER BY positionInTree DESC";
-
-               try {
-                       result = db.executeQuery(query);
-
-                       if(result == null) {
-                               Logger.warning(this, "Unable to get child 
indexes for '"+toString()+"'");
-                               return;
-                       }
-
-                       while(result.next()) {
-                               final int id = result.getInt("id");
-                               final int position = 
result.getInt("positionInTree");
-
-                               final String realName = 
result.getString("originalName");
-                               final String displayName = 
result.getString("displayName");
-
-                               final String publicKey = 
result.getString("publicKey");
-                               final String privateKey = 
result.getString("privateKey");
-
-                               final int revision = result.getInt("revision");
-
-                               final String author = 
result.getString("author");
-
-                               final Index index = new Index(queueManager, 
indexBrowser,
-                                                             id, this,
-                                                             realName, 
displayName,
-                                                             publicKey, 
privateKey,
-                                                             revision,
-                                                             author);
-
-                               set(children, position, index.getTreeNode());
-                       }
-               } catch (final java.sql.SQLException e) {
-                       Logger.warning(this, "SQLException while getting child 
of index category '"+name+"': "+e.toString());
-               }
-
-       }
-
-       public void loadChildCategories(final Vector children) {
-
-               ResultSet result;
-
-               String query;
-
-               query = "SELECT id, name, positionInTree FROM indexCategories";
-
-               if(id < 0)
-                       query = query + " WHERE parent IS NULL";
-               else
-                       query = query + " WHERE parent = "+Integer.toString(id);
-
-               query = query + " ORDER BY positionInTree DESC";
-
-               try {
-                       result = db.executeQuery(query);
-
-                       if(result == null) {
-                               Logger.error(this, "Unable to get child 
categories for '"+toString()+"'");
-                               return;
-                       }
-
-                       while(result.next()) {
-                               final int id = result.getInt("id");
-                               final int position = 
result.getInt("positionInTree");
-                               final String name = result.getString("name");
-
-                               final IndexCategory cat = new 
IndexCategory(queueManager, indexBrowser, id, this, name);
-                               cat.loadChildren();
-                               set(children, position, cat);
-                       }
-               } catch (final java.sql.SQLException e) {
-                       Logger.error(this, "SQLException while getting child of 
index category '"+name+"': "+e.toString());
-               }
-
-       }
-
-       protected void cleanChildList(final Vector children) {
-               while(children.remove(null)) {
-                       Logger.warning(this, "cleanChildList() : null removed 
!");
-               }
-       }
-
-       public void set(final Vector children, int position, final TreeNode 
node) {
-               if((node == this) || (node == null))
-                       return;
-
-               if (children == null)
-                       loadChildren();
-
-               if (position < 0) {
-                       Logger.warning(this, "set(Vector, int position, 
TreeNode) : Gave a stupid position: "+position);
-                       position = 0;
-               }
-
-               if(children.size() <= position) {
-                       children.setSize(position+1);
-               } else {
-
-                       if(children.get(position) != null) {
-                               Logger.warning(this,
-                                              "Collision in tree position: 
Moving "+Integer.toString(position)+
-                                              " to 
"+Integer.toString(children.size()));
-                               children.add(node);
-                               return;
-                       }
-               }
-
-               children.set(position, node);
-       }
-
-       public String toString() {
-               return name;
-       }
-
-       public Vector getIndexIds()
-       {
-               if(children == null)
-                       children = loadChildren();
-
-               final Vector result = new Vector();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       result.addAll(node.getIndexIds());
-               }
-
-               return result;
-       }
-
-       public Vector getIndexes()
-       {
-               if(children == null)
-                       children = loadChildren();
-
-               final Vector result = new Vector();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       result.addAll(node.getIndexes());
-               }
-
-               return result;
-       }
-
-       public Vector getAllIndexCategories()
-       {
-               if(children == null)
-                       children = loadChildren();
-
-               final Vector result = new Vector();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final Object node = 
((DefaultMutableTreeNode)it.next()).getUserObject();
-                       if (node instanceof IndexCategory) {
-                               result.add(node);
-                               
result.addAll(((IndexCategory)node).getAllIndexCategories());
-                       }
-               }
-
-               return result;
-       }
-
-
-       public Index getIndex(final int id)
-       {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       final Index result = node.getIndex(id);
-                       if (result != null)
-                               return result;
-               }
-
-               return null;
-       }
-
-       /**
-        * Returns true only if all its child are modifiable
-        */
-       public boolean isModifiable() {
-               if(children == null)
-                       children = loadChildren();
-
-               if (children.size() <= 0)
-                       return false;
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       if (!node.isModifiable())
-                               return false;
-               }
-
-               return true;
-       }
-
-
-       public boolean hasChanged() {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       if (node.hasChanged())
-                               return true;
-               }
-
-               return false;
-       }
-
-
-       public void register() {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       node.register();
-               }
-       }
-
-       public void unregister() {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       node.unregister();
-               }
-       }
-
-
-       public Element do_export(Document xmlDoc, boolean withContent) {
-               Element e = xmlDoc.createElement("indexCategory");
-
-               if (id != -1)
-                       e.setAttribute("name", name);
-
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       e.appendChild(node.do_export(xmlDoc, withContent));
-               }
-
-               unloadChildren();
-
-               return e;
-       }
-
-       /**
-        * will call create() !
-        * @param e must be a indexCategory tag
-        * @see #do_export(Document, boolean)
-        */
-       public void do_import(Element e) {
-               NodeList list = e.getChildNodes();
-
-               for (int i = 0 ; i < list.getLength(); i++) {
-                       Node n = list.item(i);
-
-                       if (n.getNodeType() == Node.ELEMENT_NODE) {
-                               Element el = (Element)n;
-
-                               if (el.getTagName().equals("fullIndex")) {
-                                       Index index = 
IndexManagementHelper.reuseIndex(queueManager, indexBrowser,
-                                                                               
       this, el.getAttribute("publicKey"),
-                                                                               
       el.getAttribute("privateKey"), false);
-                                       if (index != null) {
-                                               
index.rename(el.getAttribute("displayName"));
-                                               index.do_import(el);
-                                       }
-                               }
-
-                               if (el.getTagName().equals("indexCategory")) {
-                                       IndexCategory newCat = 
IndexManagementHelper.addIndexCategory(queueManager, indexBrowser, this,
-                                                                               
                      el.getAttribute("name"));
-                                       newCat.do_import(el);
-                               }
-                       }
-               }
-       }
-
-
-       public boolean isLeaf() {
-               return false;
-       }
-
-       /**
-        * used to create import directory
-        */
-       protected IndexTreeNode getDirectChild(String name) {
-               if(children == null)
-                       children = loadChildren();
-
-               for(final Iterator it = children.iterator();
-                   it.hasNext();) {
-                       final IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
-                       if (name.equals(node.toString()))
-                               return node;
-               }
-
-               return null;
-       }
-
-       public boolean areChildrenLoaded() {
-               return (children != null);
-       }
-}

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexConfigPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexConfigPanel.java        
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexConfigPanel.java        
2007-01-25 07:03:17 UTC (rev 11613)
@@ -54,7 +54,7 @@


        public void addTab() {
-               
configWindow.addTab(I18n.getMessage("thaw.plugin.index.browser"), panel);
+               
configWindow.addTab(I18n.getMessage("thaw.plugin.index.indexes"), panel);
        }



Copied: trunk/apps/Thaw/src/thaw/plugins/index/IndexFolder.java (from rev 
11579, trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java)
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexFolder.java                     
        (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexFolder.java     2007-01-25 
07:03:17 UTC (rev 11613)
@@ -0,0 +1,1160 @@
+package thaw.plugins.index;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Vector;
+import java.util.Observer;
+import java.util.Observable;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import thaw.core.Logger;
+import thaw.fcp.FCPQueueManager;
+import thaw.plugins.Hsqldb;
+
+
+public class IndexFolder implements IndexTreeNode, MutableTreeNode {
+
+       private static final long serialVersionUID = 2L;
+
+       private Hsqldb db;
+       private int id;
+
+       private TreeNode parentNode = null;
+       private String name = null;
+
+       private Vector children = null;
+
+       public IndexFolder(final Hsqldb db, final int id) {
+               this.id = id;
+               this.db = db;
+       }
+
+       /**
+        * @param parentNode only required if in a tree
+        */
+       public IndexFolder(final Hsqldb db, final int id, TreeNode parentNode, 
String name) {
+               this(db, id);
+               this.parentNode = parentNode;
+               this.name = name;
+       }
+
+       public boolean isInTree() {
+               return (parentNode != null);
+       }
+
+       protected void addToVector(Vector v, ResultSet set, boolean folder) 
throws SQLException {
+               if (set == null)
+                       return;
+
+               while(set.next()) {
+                       IndexTreeNode n;
+
+                       if (folder)
+                               n = new IndexFolder(db, set.getInt("id"), this, 
set.getString("name"));
+                       else
+                               n = new Index(db, set.getInt("id"), this, 
set.getString("publicKey"),
+                                             set.getInt("revision"), 
set.getString("privateKey"),
+                                             set.getString("displayName"), 
set.getBoolean("newRev"));
+
+                       int pos = set.getInt("positionInTree");
+
+                       if (v.size() <= pos) {
+                               v.setSize(pos+1);
+                       }
+
+                       if (pos >= 0 && v.get(pos) == null)
+                               v.set(pos, n);
+                       else
+                               v.add(n);
+               }
+
+       }
+
+
+       /** TREENODE **/
+
+       public Enumeration children() {
+               if (children == null)
+                       loadChildren();
+
+               synchronized(children) {
+                       return children.elements();
+               }
+       }
+
+
+       public boolean loadChildren() {
+               Logger.info(this, "Loading child for folder 
"+Integer.toString(id)+"...");
+
+               Vector v = new Vector();
+
+               synchronized(db.dbLock) {
+
+                       try {
+                               /* category first */
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, name, positionInTree FROM 
indexFolders "
+                                                                               
 + "WHERE parent = ? "
+                                                                               
 +"ORDER BY positionInTree");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, positionInTree, name FROM 
indexFolders "
+                                                                               
 + "WHERE parent IS NULL "
+                                                                               
 +"ORDER BY positionInTree");
+                               }
+
+                               addToVector(v, st.executeQuery(), true);
+
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, positionInTree, displayName, 
publicKey, privateKey, revision, newRev FROM indexes "
+                                                                               
 + "WHERE parent = ? ORDER BY positionInTree");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT id, positionInTree, displayName, 
publicKey, privateKey, revision, newRev FROM indexes "
+                                                                               
 + "WHERE parent IS NULL ORDER BY positionInTree");
+                               }
+
+                               addToVector(v, st.executeQuery(), false);
+
+                       } catch (SQLException e) {
+                               Logger.error(this, "Unable to load child list 
because: "+e.toString());
+                       }
+               }
+
+               while(v.remove(null)) { }
+
+               children = v;
+
+               return true;
+       }
+
+
+       public void unloadChildren() {
+               children = null;
+       }
+
+
+       public boolean forceReload() {
+               Logger.info(this, "forceReload()");
+               return loadChildren();
+       }
+
+
+       public boolean getAllowsChildren() {
+               return true;
+       }
+
+
+
+       public TreeNode getChildAt(int childIndex) {
+               if (children == null)
+                       loadChildren();
+
+               synchronized(children) {
+                       try {
+                               return (TreeNode)children.get(childIndex);
+                       } catch(ArrayIndexOutOfBoundsException e) {
+                               Logger.error(this, "Huho : 
ArrayIndexOutOfBoundsException ... :/");
+                               Logger.error(this, e.toString());
+                               return null;
+                       }
+               }
+       }
+
+
+       public int getChildCount() {
+               /* we use systematically this solution because else we can have 
problems with
+                * gap / other-not-funny-things-to-manage
+                */
+
+               if (children == null)
+                       loadChildren();
+
+               synchronized(children) {
+                       return children.size();
+               }
+       }
+
+
+       /**
+        * position
+        */
+       public int getIndex(TreeNode node) {
+               Logger.info(this, "getIndex()");
+
+               synchronized(db.dbLock) {
+                       try {
+                               IndexTreeNode n = (IndexTreeNode)node;
+
+                               PreparedStatement st =
+                                       
db.getConnection().prepareStatement("SELECT positionInTree FROM "+
+                                                                           ((n 
instanceof Index) ? "indexes" : "indexFolders")
+                                                                           + " 
WHERE id = ? LIMIT 1");
+
+                               st.setInt(1, n.getId());
+
+                               ResultSet set = st.executeQuery();
+
+                               if (set.next())
+                                       return set.getInt("positionInTree");
+
+                               return -1;
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to find position 
because: "+e.toString());
+                       }
+               }
+
+               return -1;
+       }
+
+       public TreeNode getParent() {
+               return parentNode;
+       }
+
+       public boolean isLeaf() {
+               return false;
+       }
+
+
+       /**
+        * entry point
+        * the target child must be in the database
+        */
+       public void insert(MutableTreeNode child, int index) {
+               Logger.notice(this, "Inserting node at 
"+Integer.toString(index)+" in node "+Integer.toString(id)+" ("+toString()+")");
+
+               if (children != null) {
+
+                       synchronized(children) {
+                               if (index < children.size())
+                                       children.add(index, child);
+                               else
+                                       children.add(child);
+
+                               while(children.remove(null)) {};
+                       }
+               }
+
+               child.setParent(this);
+
+               synchronized(db.dbLock) {
+
+                       Logger.info(this, "moving other nodes ...");
+
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET positionInTree = positionInTree + 1 "+
+                                                                               
 "WHERE parent = ? AND positionInTree >= ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, index);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                               
 "SET positionInTree = positionInTree + 1 "+
+                                                                               
 "WHERE parent = ? AND positionInTree >= ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, index);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE "+
+                                                                               
 ((child instanceof IndexFolder) ? "indexFolders" : "indexes")+
+                                                                               
 " SET parent = ?, positionInTree = ?"+
+                                                                               
 "WHERE id = ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, index);
+                                       st.setInt(3, 
((IndexTreeNode)child).getId());
+                                       st.execute();
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET positionInTree = positionInTree + 1 "+
+                                                                               
 "WHERE parent IS NULL AND positionInTree >= ?");
+                                       st.setInt(1, index);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                               
 "SET positionInTree = positionInTree + 1 "+
+                                                                               
 "WHERE parent IS NULL AND positionInTree >= ?");
+                                       st.setInt(1, index);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE "+
+                                                                               
 ((child instanceof IndexFolder) ? "indexFolders" : "indexes")+
+                                                                               
 " SET parent = ?, positionInTree = ?"+
+                                                                               
 "WHERE id = ?");
+                                       st.setNull(1, Types.INTEGER);
+                                       st.setInt(2, index);
+                                       st.setInt(3, 
((IndexTreeNode)child).getId());
+                                       st.execute();
+
+                               }
+
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while inserting node: 
"+e.toString());
+                       }
+               }
+       }
+
+
+
+       public void remove(int target_id, int pos, boolean index) {
+               if (children != null) {
+                       synchronized(children) {
+                               IndexTreeNode node;
+
+                               if (index)
+                                       node = new Index(db, target_id);
+                               else
+                                       node = new IndexFolder(db, target_id);
+
+                               children.remove(node);
+                       }
+               }
+
+               if (pos < 0) {
+                       Logger.error(this, "invalid position in tree ?!!!");
+                       pos = 0;
+               }
+
+
+               Logger.notice(this, "Removing obj pos "+Integer.toString(pos));
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET positionInTree = positionInTree - 1 "+
+                                                                               
 "WHERE parent = ? AND positionInTree > ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, pos);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                               
 "SET positionInTree = positionInTree - 1 "+
+                                                                               
 "WHERE parent = ? AND positionInTree > ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, pos);
+                                       st.execute();
+
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET positionInTree = positionInTree - 1 "+
+                                                                               
 "WHERE parent IS NULL AND positionInTree > ?");
+                                       st.setInt(1, pos);
+                                       st.execute();
+
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                               
 "SET positionInTree = positionInTree - 1 "+
+                                                                               
 "WHERE parent IS NULL AND positionInTree > ?");
+                                       st.setInt(1, pos);
+                                       st.execute();
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this,
+                                            "Error while removing node at the 
position "+Integer.toString(pos)+
+                                            " : "+e.toString());
+                       }
+               }
+       }
+
+
+       public void remove(MutableTreeNode n) {
+               IndexTreeNode node = (IndexTreeNode)n;
+
+               int t_id, pos;
+               boolean index;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+                               int id;
+
+                               st = 
db.getConnection().prepareStatement("SELECT positionInTree FROM "+
+                                                                        ((n 
instanceof Index) ? "indexes" : "indexFolders")+
+                                                                        " 
WHERE id = ?");
+
+                               st.setInt(1, node.getId());
+
+                               ResultSet set = st.executeQuery();
+
+                               if (set.next()) {
+                                       t_id = node.getId();
+                                       pos = set.getInt("positionInTree");
+                                       index = n instanceof Index;
+                               } else {
+                                       Logger.error(this, "Node not found !");
+                                       return;
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to remove node 
"+Integer.toString(node.getId())+" because: "+
+                                            e.toString());
+                               return;
+                       }
+               }
+
+               remove(t_id, pos, index);
+       }
+
+       public void remove(int pos) {
+               remove((MutableTreeNode)getChildAt(pos));
+       }
+
+
+       /**
+        * entry point
+        */
+       public void removeFromParent() {
+               if (id < 0) {
+                       Logger.error(this, "removeFromParent() : We are root 
?!");
+                       return;
+               }
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexParents "+
+                                                                        "WHERE 
(indexParents.indexId IN "+
+                                                                        " 
(SELECT indexParents.indexId FROM indexParents "+
+                                                                        "  
WHERE indexParents.folderId = ?)) "+
+                                                                        "AND 
((indexParents.folderId IN "+
+                                                                        "  
(SELECT folderParents.parentId FROM folderParents "+
+                                                                        "   
WHERE folderParents.folderId = ?)) "+
+                                                                        " OR 
(indexParents.folderId IS NULL))");
+
+                               st.setInt(1, id);
+                               st.setInt(2, id);
+                               st.execute();
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM folderParents "+
+                                                                        "WHERE 
( ((folderId IN "+
+                                                                        " 
(SELECT folderId FROM folderParents "+
+                                                                        "  
WHERE parentId = ?)) OR "+
+                                                                        "  
(folderId = ?)) "+
+                                                                        "AND 
((parentId IN "+
+                                                                        " 
(SELECT parentId FROM folderParents "+
+                                                                        "  
WHERE folderId = ?)) "+
+                                                                        "  OR 
(parentId IS NULL) ) )");
+
+                               st.setInt(1, id);
+                               st.setInt(2, id);
+                               st.setInt(3, id);
+
+                               st.execute();
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while removing from 
parent: "+e.toString());
+                       }
+               }
+
+               ((IndexFolder)parentNode).remove(this);
+       }
+
+
+       public void setParent(MutableTreeNode newParent) {
+               this.parentNode = newParent;
+               setParent(((IndexTreeNode)newParent).getId());
+       }
+
+
+       public void setUserObject(Object object) {
+               rename(object.toString());
+       }
+
+
+       /** /TREENODE **/
+
+
+       public MutableTreeNode getTreeNode() {
+               return this;
+       }
+
+
+       public void setParent(int parentId) {
+               Logger.info(this, "setParent(id)");
+
+               if (id < 0) {
+                       Logger.error(this, "setParent(): Hu ? we are root, we 
can't have a new parent ?!");
+                       return;
+               }
+
+               synchronized(db.dbLock) {
+
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                        "SET 
parent = ? "+
+                                                                        "WHERE 
id = ?");
+
+                               if (parentId < 0)
+                                       st.setNull(1, Types.INTEGER);
+                               else
+                                       st.setInt(1, parentId);
+
+                               st.setInt(2, id);
+
+                               st.execute();
+
+
+                               /* put all its child folders into its new 
parents */
+
+                               /* all its children:
+                                * SELECT folderId FROM folderParents WHERE 
parentId = IT
+                                */
+                               /* all the parent of its parent:
+                                * SELECT parentId FROM folderParents WHERE 
folderId = <parentId>
+                                */
+
+                               /* we put all its children in the parents of 
the parent folder */
+                               if (parentId >= 0) {
+                                       st = 
db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, 
parentId) "+
+                                                                               
 "SELECT a.folderId, b.parentId FROM "+
+                                                                               
 "  folderParents AS a JOIN folderParents AS b ON (a.parentId = ?) WHERE 
b.folderId = ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, parentId);
+                                       st.execute();
+                               } /* else no parent of the parent */
+
+
+                               /* we put all its children in its parent */
+                               st = 
db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, 
parentId) "+
+                                                                        " 
SELECT folderId, ? FROM folderParents "+
+                                                                        "  
WHERE parentId = ?");
+                               if (parentId >= 0)
+                                       st.setInt(1, parentId);
+                               else
+                                       st.setNull(1, Types.INTEGER);
+                               st.setInt(2, id);
+                               st.execute();
+
+                               /* we put itself in the parents of its parent */
+                               if (parentId >= 0) {
+                                       st = 
db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, 
parentId) "+
+                                                                               
 " SELECT ?, parentId FROM folderParents "+
+                                                                               
 " WHERE folderId = ?");
+                                       st.setInt(1, id);
+                                       st.setInt(2, parentId);
+                                       st.execute();
+                               }
+
+                               /* and then in its parent */
+                               st = 
db.getConnection().prepareStatement("INSERT INTO folderParents (folderId, 
parentId) "+
+                                                                        " 
VALUES (?, ?)");
+                               st.setInt(1, id);
+                               if (parentId >= 0)
+                                       st.setInt(2, parentId);
+                               else
+                                       st.setNull(2, Types.INTEGER);
+                               st.execute();
+
+
+                               st = 
db.getConnection().prepareStatement("INSERT INTO indexParents (indexId, 
folderId) "+
+                                                                        
"SELECT indexParents.indexId, folderParents.parentId "+
+                                                                        "FROM 
indexParents JOIN folderParents ON "+
+                                                                        " 
indexParents.folderId = folderParents.folderId "+
+                                                                        " 
WHERE folderParents.folderId = ?");
+                               st.setInt(1, id);
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to change parent 
because: "+e.toString());
+                       }
+
+               }
+       }
+
+       /**
+        * get Id of this node in the database.
+        */
+       public int getId() {
+               return id;
+       }
+
+
+       /**
+        * Change the name of the node.
+        */
+       public void rename(String name) {
+               if (id < 0) {
+                       Logger.error(this, "Can't rename the root node !");
+                       return;
+               }
+
+               this.name = name;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("UPDATE indexFolders "+
+                                                                        "SET 
name = ? "+
+                                                                        "WHERE 
id = ?");
+
+                               st.setString(1, name);
+                               st.setInt(2, id);
+
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while renaming the 
folder: "+e.toString());
+                       }
+               }
+       }
+
+
+       /**
+        * no choice :/
+        * else we have troubles with the Foreign keys :/
+        */
+       private void deleteChildFoldersRecursivly(int id) throws SQLException {
+               Vector children = new Vector();
+
+               PreparedStatement st =
+                       db.getConnection().prepareStatement("SELECT 
indexFolders.id FROM indexFolders where indexfolders.parent = ?");
+               st.setInt(1, id);
+
+               ResultSet set = st.executeQuery();
+
+               while(set.next()) {
+                       children.add(new Integer(set.getInt("id")));
+               }
+
+               st = db.getConnection().prepareStatement("DELETE from 
indexfolders where id = ?");
+
+               for (Iterator it = children.iterator();
+                    it.hasNext();) {
+                       Integer nextId = (Integer)it.next();
+                       deleteChildFoldersRecursivly(nextId.intValue());
+                       st.setInt(1, nextId.intValue());
+                       st.execute();
+               }
+       }
+
+
+
+       /**
+        * Entry point
+        * Remove the node from the database.<br/>
+        * Remark: Parent node must be set !
+        */
+       public void delete() {
+               if (id < 0) {
+                       Logger.error(this, "Can't remove the root node !");
+                       return;
+               }
+
+               Logger.notice(this, "DELETING FOLDER");
+
+               ((IndexFolder)parentNode).remove(this);
+
+               synchronized(db.dbLock) {
+                       try {
+                               /* we remove all the files */
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM files WHERE files.indexParent 
IN "+
+                                                                        
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = 
?)");
+
+                               st.setInt(1, id);
+
+                               st.execute();
+
+                               /* we remove all the links */
+
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM links WHERE links.indexParent 
IN "+
+                                                                        
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = 
?)");
+
+                               st.setInt(1, id);
+
+                               st.execute();
+
+                               /* we remove all the indexes */
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexes WHERE indexes.id IN "+
+                                                                        
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = 
?)");
+
+                               st.setInt(1, id);
+
+                               st.execute();
+
+
+                               /* we remove all the child folders */
+                               /* we must to it this way, else we have 
problems with foreign key */
+
+                               deleteChildFoldersRecursivly(id);
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexFolders WHERE 
indexFolders.id = ?");
+
+                               st.setInt(1, id);
+
+                               st.execute();
+
+                               /* we clean the joint tables */
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM indexParents "+
+                                                                        "WHERE 
indexId IN "+
+                                                                        
"(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = 
?)");
+                               st.setInt(1, id);
+                               st.execute();
+
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM folderParents "+
+                                                                        "WHERE 
(folderId IN "+
+                                                                        
"(SELECT folderParents.folderId FROM folderParents WHERE folderParents.parentId 
= ?))");
+                               st.setInt(1, id);
+
+                               st.execute();
+
+
+                               st = 
db.getConnection().prepareStatement("DELETE FROM folderParents "+
+                                                                        "WHERE 
folderId = ?");
+                               st.setInt(1, id);
+
+                               st.execute();
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while removing the 
folder: "+e.toString());
+                       }
+               }
+       }
+
+       /**
+        * Update from freenet / Update the freenet version, depending of the 
index kind (recursive)
+        */
+       public int insertOnFreenet(Observer observer, IndexTree indexTree, 
FCPQueueManager queueManager) {
+               int i = 0;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexId from indexParents WHERE 
folderId = ?");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexId from indexParents WHERE 
folderId IS NULL");
+                               }
+
+                               ResultSet set = st.executeQuery();
+
+
+                               while(set.next()) {
+                                       (new Index(db, 
set.getInt("indexId"))).insertOnFreenet(observer, indexTree, queueManager);
+                                       i++;
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to start insertions 
because: "+e.toString());
+                       }
+               }
+               return i;
+       }
+
+       /**
+        * Update from freenet using the given revision
+        */
+       public int downloadFromFreenet(Observer observer, IndexTree indexTree, 
FCPQueueManager queueManager) {
+               return downloadFromFreenet(observer, indexTree, queueManager, 
-1);
+       }
+
+       public int downloadFromFreenet(Observer observer, IndexTree indexTree, 
FCPQueueManager queueManager, int rev) {
+               int i = 0;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexParents.indexId "+
+                                                                               
 "FROM indexParents WHERE folderId = ?");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT id FROM indexes");
+                               }
+
+                               ResultSet set = st.executeQuery();
+
+                               while(set.next()) {
+                                       int indexId;
+
+                                       if (id >= 0)
+                                               indexId = set.getInt("indexId");
+                                       else
+                                               indexId = set.getInt("id");
+
+                                       /* TODO : give publickey too immediatly 
*/
+                                       if (rev < 0)
+                                               (new Index(db, 
indexId)).downloadFromFreenet(observer, indexTree, queueManager);
+                                       else
+                                               (new Index(db, 
indexId)).downloadFromFreenet(observer, indexTree, queueManager, rev);
+                                       i++;
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to start insertions 
because: "+e.toString());
+                       }
+               }
+
+               return i;
+       }
+
+
+       /**
+        * Get key(s)
+        */
+       public String getPublicKey() {
+               String keys = "";
+
+               Logger.info(this, "getPublicKey()");
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexes.publicKey FROM indexes "+
+                                                                               
 "WHERE indexes.id = "+
+                                                                               
 "(SELECT indexParents.id FROM indexParents "+
+                                                                               
 " WHERE indexParents.folderId = ?)");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexes.publicKey FROM indexes "+
+                                                                               
 "WHERE indexes.id = "+
+                                                                               
 "(SELECT indexParents.id FROM indexParents "+
+                                                                               
 " WHERE indexParents.folderId IS NULL)");
+                               }
+
+                               ResultSet set = st.executeQuery();
+
+                               while(set.next()) {
+                                       keys += set.getString("publicKey") + 
"\n";
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to get public keys 
because: "+e.toString());
+                       }
+               }
+
+               return keys;
+       }
+
+
+       public String getPrivateKey() {
+               String keys = "";
+
+               Logger.info(this, "getPrivateKey()");
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexes.privateKey FROM indexes "+
+                                                                               
 "WHERE indexes.id = "+
+                                                                               
 "(SELECT indexParents.id FROM indexParents "+
+                                                                               
 " WHERE indexParents.folderId = ?)");
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT indexes.privateKey FROM indexes "+
+                                                                               
 "WHERE indexes.id = "+
+                                                                               
 "(SELECT indexParents.id FROM indexParents "+
+                                                                               
 " WHERE indexParents.folderId IS NULL)");
+                               }
+
+                               ResultSet set = st.executeQuery();
+
+                               while(set.next()) {
+                                       keys += set.getString("privateKey") + 
"\n";
+                               }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to get private keys 
because: "+e.toString());
+                       }
+               }
+
+               if ("".equals(keys))
+                       return null;
+
+               return keys;
+       }
+
+       public String toString() {
+               if (id < 0)
+                       return 
thaw.core.I18n.getMessage("thaw.plugin.index.yourIndexes");
+
+               if (name != null)
+                       return name;
+
+               Logger.info(this, "toString()");
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("SELECT name from indexfolders WHERE id = ? 
LIMIT 1");
+                               st.setInt(1, id);
+                               ResultSet set = st.executeQuery();
+                               if (set.next()) {
+                                       name = set.getString("name");
+                                       return name;
+                               }
+
+                               Logger.error(this, "toString(): not found in 
the db ?!");
+                               return null;
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to get name because: 
"+e.toString());
+                       }
+               }
+
+               return null;
+       }
+
+
+       public boolean equals(Object o) {
+               if (o == null || !(o instanceof IndexFolder))
+                       return false;
+
+               if (((IndexTreeNode)o).getId() == getId())
+                       return true;
+               return false;
+       }
+
+
+       public boolean isModifiable() {
+               /* disable for performance reasons */
+               return false;
+       }
+
+
+       public boolean realIsModifiable() {
+
+               if (children != null) {
+                       synchronized(children) {
+
+                               for (Iterator it = children.iterator();
+                                    it.hasNext();) {
+                                       IndexTreeNode child = 
(IndexTreeNode)it.next();
+
+                                       if (!child.isModifiable()) {
+                                               return false;
+                                       }
+                               }
+                       }
+
+                       return true;
+               }
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               if (id >= 0) {
+                                       st = 
db.getConnection().prepareStatement("SELECT count(indexes.id) FROM "+
+                                                                               
 "indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
+                                                                               
 "WHERE indexParents.folderId = ?");
+
+                                       st.setInt(1, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("SELECT count(indexes.id) FROM "+
+                                                                               
 "indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
+                                                                               
 "WHERE indexParents.folderId IS NULL");
+                               }
+
+                               ResultSet set = st.executeQuery();
+
+                               if(set.next()) {
+                                       int res;
+
+                                       res = set.getInt(1);
+
+                                       if (res > 0)
+                                               return false;
+                                       else
+                                               return true;
+                               }
+                       } catch(SQLException e) {
+                               Logger.error(this, "unable to know if the 
folder contains only modifiable indexes because: "+e.toString());
+                       }
+               }
+               return false;
+       }
+
+
+       public boolean setHasChangedFlag(boolean flag) {
+               setHasChangedFlagInMem(flag);
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+                               if (id > 0) {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET newRev = ? "+
+                                                                               
 "WHERE id IN "+
+                                                                               
 "(SELECT indexParents.indexId FROM indexParents WHERE indexParents.folderId = 
?)");
+                                       st.setInt(2, id);
+                               } else {
+                                       st = 
db.getConnection().prepareStatement("UPDATE indexes "+
+                                                                               
 "SET newRev = ?");
+                               }
+                               st.setBoolean(1, flag);
+
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while changing 
'hasChanged' flag: "+e.toString());
+                               return false;
+                       }
+               }
+
+               return true;
+       }
+
+       public boolean setHasChangedFlagInMem(boolean flag) {
+               if (children != null) {
+
+                       synchronized(children) {
+                               for (Iterator it = children.iterator();
+                                    it.hasNext();) {
+                                       IndexTreeNode child = 
(IndexTreeNode)it.next();
+
+                                       child.setHasChangedFlagInMem(flag);
+                               }
+                       }
+               }
+
+               return true;
+       }
+
+
+       private boolean lastHasChangedValue = false;
+       private boolean hasLastHasChangedValueBeenSet = false;
+
+       public void forceHasChangedReload() {
+               hasLastHasChangedValueBeenSet = false;
+       }
+
+       public boolean hasChanged() {
+               if (children != null) {
+
+                       synchronized(children) {
+                               for (Iterator it = children.iterator();
+                                    it.hasNext();) {
+                                       IndexTreeNode child = 
(IndexTreeNode)it.next();
+
+                                       if (child.hasChanged())
+                                               return true;
+                               }
+
+                               return false;
+                       }
+               }
+
+               /* It's dirty and will probably cause graphical bug :/ */
+               if (hasLastHasChangedValueBeenSet)
+                       return lastHasChangedValue;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("SELECT indexes.id "+
+                                                                        "FROM 
indexes JOIN indexParents ON indexes.id = indexParents.indexId "+
+                                                                        "WHERE 
indexParents.folderId = ? AND indexes.newRev = TRUE LIMIT 1");
+                               st.setInt(1, id);
+
+                               ResultSet set = st.executeQuery();
+
+                               boolean ret;
+
+                               ret = set.next();
+
+                               lastHasChangedValue = ret;
+                               hasLastHasChangedValueBeenSet = true;
+
+                               return ret;
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while trying to see 
if there is any change: "+e.toString());
+                       }
+               }
+
+               return false;
+       }
+
+       /**
+        * Will export private keys too !<br/>
+        * TODO: Improve perfs
+        */
+       public Element do_export(Document xmlDoc, boolean withContent) {
+               Element e = xmlDoc.createElement("indexCategory");
+
+               if (id != -1)
+                       e.setAttribute("name", name);
+
+               if(children == null)
+                       loadChildren();
+
+               for(final Iterator it = children.iterator();
+                   it.hasNext();) {
+                       final IndexTreeNode node = (IndexTreeNode)(it.next());
+                       e.appendChild(node.do_export(xmlDoc, withContent));
+               }
+
+               unloadChildren();
+
+               return e;
+       }
+
+       public void do_import(IndexBrowserPanel indexBrowser, Element e) {
+               NodeList list = e.getChildNodes();
+
+               for (int i = 0 ; i < list.getLength(); i++) {
+                       Node n = list.item(i);
+
+                       if (n.getNodeType() == Node.ELEMENT_NODE) {
+                               Element el = (Element)n;
+
+                               if (el.getTagName().equals("fullIndex")) {
+                                       Index index = 
IndexManagementHelper.reuseIndex(null, indexBrowser,
+                                                                               
       this, el.getAttribute("publicKey"),
+                                                                               
       el.getAttribute("privateKey"), false);
+                                       if (index != null) {
+                                               
index.rename(el.getAttribute("displayName"));
+                                               index.do_import(indexBrowser, 
el);
+                                       }
+                               }
+
+                               if (el.getTagName().equals("indexCategory")) {
+                                       IndexFolder newCat = 
IndexManagementHelper.addIndexFolder(indexBrowser, this,
+                                                                               
                  el.getAttribute("name"));
+                                       newCat.do_import(indexBrowser, el);
+                               }
+                       }
+               }
+
+       }
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java   
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexManagementHelper.java   
2007-01-25 07:03:17 UTC (rev 11613)
@@ -14,6 +14,9 @@
 import java.util.Iterator;
 import java.util.Vector;

+import java.util.Observer;
+import java.util.Observable;
+
 import javax.swing.AbstractButton;
 import javax.swing.JButton;
 import javax.swing.JDialog;
@@ -24,9 +27,14 @@
 import javax.swing.JPanel;
 import javax.swing.JPopupMenu;
 import javax.swing.JTextArea;
+import javax.swing.JCheckBox;
 import javax.swing.JTextField;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.MutableTreeNode;
 import javax.swing.tree.DefaultMutableTreeNode;

+import java.sql.*;
+
 import thaw.core.FileChooser;
 import thaw.core.FreenetURIHelper;
 import thaw.core.I18n;
@@ -36,10 +44,11 @@
 import thaw.fcp.FCPClientPut;
 import thaw.fcp.FCPQueueManager;
 import thaw.fcp.FCPTransferQuery;
+import thaw.fcp.FCPGenerateSSK;
 import thaw.plugins.Hsqldb;

 /**
- * Index.java, IndexCategory.java and IndexTree.java must NEVER use this 
helper (to avoid loops).
+ * Index.java, IndexFolder.java and IndexTree.java must NEVER use this helper 
(to avoid loops).
  */
 public class IndexManagementHelper {

@@ -74,7 +83,9 @@
                        this.actionSource = actionSource;
                        target = null;
                        this.queueManager = queueManager;
-                       actionSource.addActionListener(this);
+
+                       if (actionSource != null)
+                               actionSource.addActionListener(this);
                }

                public AbstractButton getActionSource() {
@@ -115,14 +126,16 @@



-       public static class IndexCreator extends BasicIndexAction {
+       public static class IndexCreator extends BasicIndexAction implements 
Observer {
                public IndexCreator(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
                        super(queueManager, indexBrowser, actionSource);
                }

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node == null) || (node 
instanceof IndexCategory));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node == null) || 
(node instanceof IndexFolder));
                }

                public void apply() {
@@ -133,31 +146,100 @@
                        if (name == null)
                                return;

-                       IndexManagementHelper.createIndex(getQueueManager(), 
getIndexBrowserPanel(), (IndexCategory)getTarget(), name);
+                       /* will create a dedicated IndexCreator */
+                       IndexManagementHelper.createIndex(getQueueManager(), 
getIndexBrowserPanel(), (IndexFolder)getTarget(), name);
                }
-       }

-       public static Index createIndex(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, IndexCategory target, final String name) {
-               if (target == null)
-                       target = indexBrowser.getIndexTree().getRoot();

-               if ((name == null) || (name.indexOf("/") >= 0) || 
name.indexOf("\\") >= 0) {
-                       Logger.error(new IndexManagementHelper(), "invalid 
name");
-                       return null;
+               private String name;
+
+               /**
+                * Don't use directly
+                */
+               public void createIndex(String name) {
+                       if (getTarget() == null)
+                               
setTarget(getIndexBrowserPanel().getIndexTree().getRoot());
+
+                       if ((name == null) || (name.indexOf("/") >= 0) || 
name.indexOf("\\") >= 0) {
+                               Logger.error(new IndexManagementHelper(), 
"invalid name");
+                               return;
+                       }
+
+                       this.name = name;
+
+                       FCPGenerateSSK sskGenerator;
+
+                       sskGenerator = new FCPGenerateSSK();
+                       sskGenerator.addObserver(this);
+                       sskGenerator.start(getQueueManager());
                }

-               final Index index = new Index(queueManager, indexBrowser, -1, 
target, name, name, null, null, 0, null);

-               index.generateKeys();
-               index.create();
+               public void update(Observable o, Object param) {
+                       FCPGenerateSSK sskGenerator = (FCPGenerateSSK)o;
+                       Hsqldb db = getIndexBrowserPanel().getDb();

-               indexBrowser.getIndexTree().addToIndexCategory(target, index);
+                       synchronized(db.dbLock) {
+                               try {
+                                       PreparedStatement st;

-               return index;
+                                       int id = DatabaseManager.getNextId(db, 
"indexes");
+
+                                       if (id == -1)
+                                               return;
+
+                                       st = 
db.getConnection().prepareStatement("INSERT INTO indexes "+
+                                                                               
 "(id, originalName, displayName, "+
+                                                                               
 " publicKey, privateKey, author, "+
+                                                                               
 " positionInTree, revision, "+
+                                                                               
 " newRev, parent) "+
+                                                                               
 "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+                                       /* TODO : Author */
+
+                                       st.setInt(1, id);
+                                       st.setString(2, name);
+                                       st.setString(3, name);
+                                       st.setString(4, 
sskGenerator.getPublicKey());
+                                       st.setString(5, 
sskGenerator.getPrivateKey());
+                                       st.setNull(6, Types.VARCHAR);
+                                       st.setInt(7, 0 /* positionInTree */);
+                                       st.setInt(8, 0 /* revision */);
+                                       st.setBoolean(9, false);
+
+                                       if (getTarget().getId() >= 0)
+                                               st.setInt(10, 
getTarget().getId());
+                                       else
+                                               st.setNull(10, Types.INTEGER);
+
+                                       st.execute();
+
+                                       Index index = new Index(db, id, 
(TreeNode)getTarget(),
+                                                               
sskGenerator.getPublicKey(), 0, sskGenerator.getPrivateKey(),
+                                                               name, false);
+
+                                       
((MutableTreeNode)getTarget()).insert(((MutableTreeNode)index), 0);
+
+
+                                       
getIndexBrowserPanel().getIndexTree().refresh(getTarget());
+                               } catch(SQLException e) {
+                                       Logger.error(new 
IndexManagementHelper(), "Error while creating index: "+e.toString());
+                               }
+                       }
+               }
        }


+       public static void createIndex(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, IndexFolder target, final String name) {

+               IndexCreator creator = new IndexCreator(queueManager, 
indexBrowser, null);
+               creator.setTarget(target);
+               creator.createIndex(name);
+
+       }
+
+
+
        public static class KeyAsker implements ActionListener, MouseListener {
                private JButton okButton;
                private JButton cancelButton;
@@ -165,28 +247,56 @@

                private JTextField publicKeyField = null;
                private JTextField privateKeyField = null;
+               private JCheckBox  publishPrivateKeyBox = null;

                private JPopupMenu popupMenuA;
                private JPopupMenu popupMenuB;

                public KeyAsker() {
+
                }


-               /**
-                * @return String[0] == publicKey ; String[1] == privateKey ; 
public or private are null if unchanged
-                */
-               public static String[] askKeys(final boolean askPrivateKey,
+               public static KeyAsker askKeys(final boolean askPrivateKey,
                                               final String defaultPublicKey,
                                               final String defaultPrivateKey,
+                                              final boolean 
defaultPublishPrivateKey,
+                                              final boolean 
enablePublishPrivateKeyChoice,
                                               final IndexBrowserPanel 
indexBrowser) {
-                       return ((new KeyAsker()).askKeysBis(askPrivateKey, 
defaultPublicKey, defaultPrivateKey, indexBrowser));
+                       KeyAsker asker = new KeyAsker();
+                       asker.askKeysBis(askPrivateKey, defaultPublicKey,
+                                        defaultPrivateKey, 
defaultPublishPrivateKey,
+                                        enablePublishPrivateKeyChoice, 
indexBrowser);
+                       if (asker.getPublicKey() != null)
+                               return asker;
+                       else
+                               return null;
                }

-               public synchronized String[] askKeysBis(final boolean 
askPrivateKey,
-                                                       String defaultPublicKey,
-                                                       String 
defaultPrivateKey,
-                                                       final IndexBrowserPanel 
indexBrowser) {
+
+               private String publicKeyResult = null;
+               private String privateKeyResult = null;
+               private boolean publishPrivateKey = false;
+
+
+               public String getPublicKey() {
+                       return publicKeyResult;
+               }
+
+               public String getPrivateKey() {
+                       return privateKeyResult;
+               }
+
+               public boolean getPublishPrivateKey() {
+                       return publishPrivateKey;
+               }
+
+               public synchronized void askKeysBis(final boolean askPrivateKey,
+                                                   String defaultPublicKey,
+                                                   String defaultPrivateKey,
+                                                   boolean 
defaultPublishPrivateKey,
+                                                   final boolean 
enablePublishPrivateKeyChoice,
+                                                   final IndexBrowserPanel 
indexBrowser) {
                        formState = 0;

                        if (defaultPublicKey == null)
@@ -201,7 +311,9 @@

                        publicKeyField = new JTextField(defaultPublicKey);
                        privateKeyField = new JTextField(defaultPrivateKey);
-
+                       publishPrivateKeyBox = new 
JCheckBox(I18n.getMessage("thaw.plugin.index.publishPrivateKey"),
+                                                            
defaultPublishPrivateKey);
+                       
publishPrivateKeyBox.setEnabled(enablePublishPrivateKeyChoice);
                        final JPanel subPanelA = new JPanel(); /* left => 
labels */
                        final JPanel subPanelB = new JPanel(); /* right => 
textfield */

@@ -220,6 +332,7 @@
                        if (askPrivateKey) {
                                subPanelA.add(new 
JLabel(I18n.getMessage("thaw.plugin.index.indexPrivateKey")+" "), 
BorderLayout.WEST);
                                subPanelB.add(privateKeyField, 
BorderLayout.CENTER);
+
                                popupMenuB = new JPopupMenu();
                                item = new 
JMenuItem(I18n.getMessage("thaw.common.paste"));
                                popupMenuB.add(item);
@@ -231,20 +344,26 @@
                        frame.getContentPane().add(subPanelB, 
BorderLayout.CENTER);

                        final JPanel subPanelC = new JPanel();
-                       subPanelC.setLayout(new GridLayout(1, 2));
+                       subPanelC.setLayout(new GridLayout(2, 1));

+                       final JPanel subSubPanelC = new JPanel();
+                       subSubPanelC.setLayout(new GridLayout(1, 2));
+
                        cancelButton = new 
JButton(I18n.getMessage("thaw.common.cancel"));
                        okButton = new 
JButton(I18n.getMessage("thaw.common.ok"));

                        cancelButton.addActionListener(this);
                        okButton.addActionListener(this);

-                       subPanelC.add(okButton);
-                       subPanelC.add(cancelButton);
+                       subSubPanelC.add(okButton);
+                       subSubPanelC.add(cancelButton);

+                       subPanelC.add(publishPrivateKeyBox);
+                       subPanelC.add(subSubPanelC);
+
                        frame.getContentPane().add(subPanelC, 
BorderLayout.SOUTH);

-                       frame.setSize(700, 100);
+                       frame.setSize(700, 120);
                        frame.setVisible(true);

                        try {
@@ -256,26 +375,28 @@
                        frame.setVisible(false);

                        if (formState == 2)
-                               return null;
+                               return;

-                       final String[] keys = new String[2];
+                       publicKeyResult = publicKeyField.getText();

-                       keys[0] = publicKeyField.getText();
                        if (askPrivateKey)
-                               keys[1] = privateKeyField.getText();
-                       else
-                               keys[1] = null;
+                               privateKeyResult = privateKeyField.getText();

                        frame.dispose();

-                       if ((keys[0] == null) || (keys[0].length() < 20))
-                               return null;
+                       if ((publicKeyResult == null) || 
(publicKeyResult.length() < 20))
+                               {
+                                       publicKeyResult = null;
+                                       privateKeyResult = null;
+                               }

-                       if ((keys[1] == null) || (keys[1].length() < 20))
-                               keys[1] = null;
+                       if ((privateKeyResult == null) || 
(privateKeyResult.length() < 20))
+                               privateKeyResult = null;
+                       else
+                               publishPrivateKey = 
publishPrivateKeyBox.isSelected();

+                       Logger.info(this, "public : "+publicKeyResult + " ; 
Private : "+privateKeyResult);

-                       return keys;
                }

                public synchronized void actionPerformed(final ActionEvent e) {
@@ -313,6 +434,7 @@

        }

+
        public static class IndexKeyModifier extends BasicIndexAction 
implements Runnable {

                public IndexKeyModifier(final IndexBrowserPanel indexBrowser, 
final AbstractButton actionSource) {
@@ -321,19 +443,25 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index));
                }

                public void apply() {
                        final Index index = ((Index)getTarget());

-                       final String[] keys = KeyAsker.askKeys(true, 
index.getPublicKey(), index.getPrivateKey(), getIndexBrowserPanel());
+                       final KeyAsker asker = KeyAsker.askKeys(true, 
index.getPublicKey(), index.getPrivateKey(), index.getPublishPrivateKey(), 
true, getIndexBrowserPanel());

-                       if (keys == null)
+                       if (asker == null)
                                return;

-                       index.setPrivateKey(keys[1]);
-                       index.setPublicKey(keys[0]);
+                       /* Could be done in one shot ... but this way is so 
easier .... :) */
+                       index.setPrivateKey(asker.getPrivateKey());
+                       
index.setPublishPrivateKey(asker.getPublishPrivateKey());
+                       index.setPublicKey(asker.getPublicKey());
+
+                       getIndexBrowserPanel().getIndexTree().refresh(index);
                }
        }

@@ -345,41 +473,48 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node == null) || (node 
instanceof IndexCategory));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node == null) || 
(node instanceof IndexFolder));
                }

                public void apply() {
-                       String keys[];
+                       KeyAsker asker;
                        String publicKey = null;
                        String privateKey = null;
+                       boolean publishPrivate = false;

-                       keys = KeyAsker.askKeys(true, "USK@", "SSK@", 
getIndexBrowserPanel());
+                       asker = KeyAsker.askKeys(true, "USK@", "SSK@", false, 
false, getIndexBrowserPanel());

-                       if (keys == null)
+                       if (asker == null)
                                return;

-                       publicKey = keys[0];
-                       privateKey = keys[1];
+                       publicKey = asker.getPublicKey();
+                       privateKey = asker.getPrivateKey();
+                       //publishPrivate = asker.getPublishPrivateKey(); /* 
useless ; will be reset when downloading */

-                       IndexManagementHelper.reuseIndex(getQueueManager(), 
getIndexBrowserPanel(), (IndexCategory)getTarget(), publicKey, privateKey);
+                       IndexManagementHelper.reuseIndex(getQueueManager(), 
getIndexBrowserPanel(), (IndexFolder)getTarget(), publicKey, privateKey);
                }
        }


-       public static Index addIndex(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser, final IndexCategory target, final String 
publicKey) {
+       public static Index addIndex(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser, final IndexFolder target, final String 
publicKey) {
                return IndexManagementHelper.reuseIndex(queueManager, 
indexBrowser, target, publicKey, null);
        }

-       public static Index reuseIndex(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, final IndexCategory target, String 
publicKey, String privateKey) {
+       public static Index reuseIndex(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, final IndexFolder target, String 
publicKey, String privateKey) {
                return reuseIndex(queueManager, indexBrowser, target, 
publicKey, privateKey, true);
        }

        /**
-        * Can be use directly
         * @param privateKey Can be null
+        * @param queueManager only needed if load == true
         */
-       public static Index reuseIndex(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, final IndexCategory target, String 
publicKey, String privateKey,
-                                     boolean load) {
+       public static Index reuseIndex(final FCPQueueManager queueManager,
+                                      final IndexBrowserPanel indexBrowser,
+                                      final IndexFolder target,
+                                      String publicKey, String privateKey,
+                                      boolean load) {

                publicKey = FreenetURIHelper.cleanURI(publicKey);
                privateKey = FreenetURIHelper.cleanURI(privateKey);
@@ -402,40 +537,93 @@
                        return null;
                }

-               IndexCategory parent;
+               IndexFolder parent;

-               if ((target != null) && (target instanceof IndexCategory))
+               if (target != null)
                        parent = target;
                else
                        parent = indexBrowser.getIndexTree().getRoot();

-               final Index index = new Index(queueManager, indexBrowser, -2, 
parent, name, name, publicKey, privateKey, 0, null);
+               int revision = FreenetURIHelper.getUSKRevision(publicKey);

-               indexBrowser.getUnknownIndexList().removeLink(index);
+               if (revision < 0)
+                       return null;

-               index.create();
+               Hsqldb db = indexBrowser.getDb();

+               Index index = null;
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               int id = DatabaseManager.getNextId(db, 
"indexes");
+
+                               if (id == -1)
+                                       return null;
+
+                               st = 
db.getConnection().prepareStatement("INSERT INTO indexes "+
+                                                                        "(id, 
originalName, displayName, "+
+                                                                        " 
publicKey, privateKey, author, "+
+                                                                        " 
positionInTree, revision, "+
+                                                                        " 
newRev, parent) "+
+                                                                        
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+
+                               /* TODO : Author */
+
+                               st.setInt(1, id);
+                               st.setString(2, name);
+                               st.setString(3, name);
+                               st.setString(4, publicKey);
+                               st.setString(5, privateKey);
+                               st.setNull(6, Types.VARCHAR);
+                               st.setInt(7, 0 /* positionInTree */);
+                               st.setInt(8, revision);
+                               st.setBoolean(9, false);
+
+                               if (parent.getId() > 0)
+                                       st.setInt(10, parent.getId());
+                               else
+                                       st.setNull(10, Types.INTEGER);
+
+                               st.execute();
+
+                               index = new Index(db, id, (TreeNode)parent,
+                                                 publicKey, revision, 
privateKey,
+                                                 name, false);
+
+                       } catch(SQLException e) {
+                               Logger.error(new IndexManagementHelper(), 
"Error while adding index: "+e.toString());
+                               return null;
+                       }
+
+               }
+
                if (load)
-                       index.updateFromFreenet(-1);
+                       download(queueManager, indexBrowser, index);

-               parent.insert(index.getTreeNode(), 0);
+               ((MutableTreeNode)parent).insert(((MutableTreeNode)index), 0);

-               indexBrowser.getIndexTree().reloadModel(parent);
+               indexBrowser.getIndexTree().refresh(parent);

+               indexBrowser.getUnknownIndexList().removeLink(index);
+
                return index;
        }




-       public static class IndexCategoryAdder extends BasicIndexAction {
-               public IndexCategoryAdder(final FCPQueueManager queueManager, 
final IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
-                       super(queueManager, indexBrowser, actionSource);
+       public static class IndexFolderAdder extends BasicIndexAction {
+               public IndexFolderAdder(final IndexBrowserPanel indexBrowser, 
final AbstractButton actionSource) {
+                       super(null, indexBrowser, actionSource);
                }

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node == null) || (node 
instanceof IndexCategory));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node == null) || 
(node instanceof IndexFolder));
                }

                public void apply() {
@@ -443,28 +631,62 @@
                                                                           
I18n.getMessage("thaw.plugin.index.categoryName"),
                                                                           
I18n.getMessage("thaw.plugin.index.newCategory"));

-                       
IndexManagementHelper.addIndexCategory(getQueueManager(), 
getIndexBrowserPanel(), (IndexCategory)getTarget(), name);
+                       
IndexManagementHelper.addIndexFolder(getIndexBrowserPanel(), 
(IndexFolder)getTarget(), name);
                }
        }


-       public static IndexCategory addIndexCategory(final FCPQueueManager 
queueManager, final IndexBrowserPanel indexBrowser, IndexCategory target, final 
String name) {
+       public static IndexFolder addIndexFolder(final IndexBrowserPanel 
indexBrowser, IndexFolder target, final String name) {
                if (target == null)
                        target = indexBrowser.getIndexTree().getRoot();

-               final IndexCategory newCat = new IndexCategory(queueManager, 
indexBrowser, -2, target, name);
+               IndexFolder folder = null;

-               newCat.create();
+               synchronized(indexBrowser.getDb().dbLock) {

-               indexBrowser.getIndexTree().addToIndexCategory(target, newCat);
+                       try {
+                               PreparedStatement st;

-               return newCat;
+                               int nextId = 
DatabaseManager.getNextId(indexBrowser.getDb(), "indexFolders");
+
+                               if (nextId < -1)
+                                       return null;
+
+                               st = 
indexBrowser.getDb().getConnection().prepareStatement("INSERT INTO indexFolders 
"+
+                                                                               
           "(id, name, positionInTree, modifiableIndexes, parent) "+
+                                                                               
           "VALUES (?, ?, ?, ?, ?)");
+
+                               st.setInt(1, nextId);
+                               st.setString(2, name);
+                               st.setInt(3, 0 /* position */);
+                               st.setBoolean(4, true /* modifiable : obsolete 
*/);
+
+                               if (target.getId() > 0)
+                                       st.setInt(5, target.getId());
+                               else
+                                       st.setNull(5, Types.INTEGER);
+
+                               st.execute();
+
+                               folder = new IndexFolder(indexBrowser.getDb(), 
nextId, target, name);
+
+                       } catch(SQLException e) {
+                               Logger.error(new IndexManagementHelper(), 
"Error while creating folder: "+e.toString());
+
+                               return null;
+                       }
+               }
+
+               ((MutableTreeNode)target).insert(((MutableTreeNode)folder), 0);
+               indexBrowser.getIndexTree().refresh(target);
+
+               return folder;
        }


-       public static class IndexDownloader extends BasicIndexAction implements 
Runnable {
-               public IndexDownloader(final AbstractButton actionSource) {
-                       super(null, null, actionSource);
+       public static class IndexHasChangedFlagReseter extends BasicIndexAction 
implements Runnable {
+               public IndexHasChangedFlagReseter(IndexBrowserPanel 
indexBrowser, final AbstractButton actionSource) {
+                       super(null, indexBrowser, actionSource);
                }

                public void setTarget(final IndexTreeNode node) {
@@ -472,30 +694,136 @@
                }

                public void apply() {
-                       if (getTarget() != null)
-                               getTarget().updateFromFreenet(-1);
+                       getTarget().setHasChangedFlag(false);
+                       
getIndexBrowserPanel().getIndexTree().redraw(getTarget());
+               }
+       }
+
+
+       public static class IndexDownloader extends BasicIndexAction implements 
Runnable, Observer {
+               public boolean allStarted;
+               public int toRemove;
+
+               public IndexDownloader(FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
+                       super(queueManager, indexBrowser, actionSource);
+               }
+
+               public void setTarget(final IndexTreeNode node) {
+                       super.setTarget(node);
+               }
+
+               public void apply() {
+                       int i;
+
+                       toRemove = 0;
+                       allStarted = false;
+
+                       i = getTarget().downloadFromFreenet(this, 
getIndexBrowserPanel().getIndexTree(), getQueueManager());
+
+                       
getIndexBrowserPanel().getIndexTree().redraw(getTarget());
+
+                       if (i > 0)
+                               
getIndexBrowserPanel().getIndexProgressBar().addTransfer(i);
                        else
-                               
getIndexBrowserPanel().getIndexTree().getRoot().updateFromFreenet(-1);
+                               Logger.notice(this, "No download started ?!");
+
+                       allStarted = true;
                }
+
+               public void update(Observable o, Object param) {
+                       
getIndexBrowserPanel().getIndexTree().redraw(((Index)o), true);
+
+
+                       if 
(o.equals(getIndexBrowserPanel().getTables().getFileTable().getFileList())) {
+                               
getIndexBrowserPanel().getTables().getFileTable().refresh();
+                       }
+
+                       if 
(o.equals(getIndexBrowserPanel().getTables().getLinkTable().getLinkList())) {
+                               
getIndexBrowserPanel().getTables().getLinkTable().refresh();
+                       }
+
+                       
getIndexBrowserPanel().getUnknownIndexList().addLinks((LinkList)o);
+
+                       toRemove++;
+
+                       if (allStarted) {
+                               
getIndexBrowserPanel().getIndexProgressBar().removeTransfer(toRemove);
+                               toRemove = 0;
+                       }
+               }
        }

-       public static class IndexUploader extends BasicIndexAction implements 
Runnable {
-               public IndexUploader(final AbstractButton actionSource) {
-                       super(null, null, actionSource);
+
+
+       public static boolean download(FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, IndexTreeNode target) {
+               IndexDownloader downloader = new IndexDownloader(queueManager, 
indexBrowser, null);
+               downloader.setTarget(target);
+
+               Thread th = new Thread(downloader);
+               th.start();
+
+               return true;
+       }
+
+
+       public static class IndexUploader extends BasicIndexAction implements 
Runnable, Observer {
+               private boolean allStarted = false;
+               private int toRemove = 0;
+
+               public IndexUploader(FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, final AbstractButton actionSource) {
+                       super(queueManager, indexBrowser, actionSource);
                }

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && 
node.isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
node.isModifiable());
                }

                public void apply() {
-                       if (getTarget() != null)
-                               getTarget().update();
+                       int i;
+
+                       toRemove = 0;
+                       allStarted = false;
+
+                       i = getTarget().insertOnFreenet(this, 
getIndexBrowserPanel().getIndexTree(), getQueueManager());
+
+                       
getIndexBrowserPanel().getIndexTree().redraw(getTarget());
+
+                       if (i > 0)
+                               
getIndexBrowserPanel().getIndexProgressBar().addTransfer(i);
+                       else
+                               Logger.notice(this, "No insertion started ?!");
+
+                       allStarted = true;
                }
+
+               public void update(Observable o, Object param) {
+                       
getIndexBrowserPanel().getIndexTree().redraw(((Index)o));
+
+                       toRemove++;
+
+                       if (allStarted) {
+                               
getIndexBrowserPanel().getIndexProgressBar().removeTransfer(toRemove);
+                               toRemove = 0;
+                       }
+               }
+
        }


+       public static boolean insert(FCPQueueManager queueManager, 
IndexBrowserPanel indexBrowser, IndexTreeNode target) {
+               IndexUploader uploader = new IndexUploader(queueManager, 
indexBrowser, null);
+               uploader.setTarget(target);
+
+               Thread th = new Thread(uploader);
+               th.start();
+
+               return true;
+       }
+
+
        public static class PublicKeyCopier extends BasicIndexAction {
                public PublicKeyCopier(final AbstractButton actionSource) {
                        super(null, null, actionSource);
@@ -503,7 +831,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled(node != null);
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled(node != null);
                }

                public void apply() {
@@ -530,7 +860,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index) && node.isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index) && node.isModifiable());
                }

                public void apply() {
@@ -559,7 +891,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled(node != null);
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled(node != null);
                }

                public void apply() {
@@ -589,7 +923,7 @@

                node.rename(newName);

-               indexBrowser.getIndexTree().reloadModel(node.getTreeNode());
+               indexBrowser.getIndexTree().refresh(node);
        }


@@ -601,7 +935,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index));
                }

                public void apply() {
@@ -637,7 +973,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index));
                }

                public void apply() {
@@ -668,9 +1006,11 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled(node != null
-                                                    && 
(getIndexBrowserPanel().getIndexTree() != null
-                                                        && node != 
getIndexBrowserPanel().getIndexTree().getRoot()));
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled(node != null
+                                                            && 
(getIndexBrowserPanel().getIndexTree() != null
+                                                                && node != 
getIndexBrowserPanel().getIndexTree().getRoot()));
                }

                public void apply() {
@@ -683,17 +1023,14 @@
                if (node == null)
                        return;

-               final DefaultMutableTreeNode parent = 
(DefaultMutableTreeNode)node.getTreeNode().getParent();
-
-               if (parent != null)
-                       parent.remove(node.getTreeNode());
-
+               IndexFolder folder = 
(IndexFolder)(node.getTreeNode().getParent());
                node.delete();

-               if (parent != null)
-                       indexBrowser.getIndexTree().reloadModel(parent);
-               else
-                       indexBrowser.getIndexTree().reloadModel();
+               if (folder != null) {
+                       indexBrowser.getIndexTree().refresh(folder);
+               } else {
+                       indexBrowser.getIndexTree().refresh();
+               }
        }


@@ -708,7 +1045,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index) && ((Index)node).isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index) && ((Index)node).isModifiable());
                }

                public void apply() {
@@ -754,7 +1093,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index) && ((Index)node).isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index) && ((Index)node).isModifiable());
                }

                public void apply() {
@@ -789,46 +1130,95 @@
        }

        /**
-        * @param files See thaw.plugins.index.File
+        * @param files See java.io.File
         */
        public static void addFiles(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser,
                                    final Index target, final Vector files, 
final String category, final boolean insert) {
                if ((target == null) || (files == null))
                        return;

-               for(final Iterator it = files.iterator();
-                   it.hasNext();) {
+               Hsqldb db;
+               PreparedStatement selectSt;
+               PreparedStatement st;
+               int nextId;

-                       final java.io.File ioFile = (java.io.File)it.next();
+               db = indexBrowser.getDb();

-                       FCPTransferQuery insertion = null;
+               synchronized(db.dbLock) {
+                       try {
+                               selectSt = 
db.getConnection().prepareStatement("SELECT id from files WHERE indexParent = ? 
AND LOWER(filename) LIKE ? LIMIT 1");
+                               st = 
db.getConnection().prepareStatement("INSERT INTO files "+
+                                                                        "(id, 
filename, publicKey, localPath, mime, size, category, indexParent) "+
+                                                                        
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+                               nextId = DatabaseManager.getNextId(db, "files");

-                       if(insert) {
-                               insertion = new FCPClientPut(ioFile, 0, 0, null,
-                                                            null, 
FCPClientPut.DEFAULT_INSERTION_PRIORITY,
-                                                            true, 0, false);
-                               
queueManager.addQueryToThePendingQueue(insertion);
-                       } else {
-                               insertion = new FCPClientPut(ioFile, 0, 0, null,
-                                                            null, 
FCPClientPut.DEFAULT_INSERTION_PRIORITY,
-                                                            true, 2, true); /* 
getCHKOnly */
-                               insertion.start(queueManager);
+                               if (nextId < 0)
+                                       return;
+                       } catch(SQLException e) {
+                               Logger.error(new IndexManagementHelper(), 
"Exception while trying to add file: "+e.toString());
+                               return;
                        }

-                       final thaw.plugins.index.File file = new 
thaw.plugins.index.File(indexBrowser.getDb(),
-                                                                               
         ioFile.getPath(),
-                                                                               
         category, target,
-                                                                               
         insertion);

-                       ((FCPClientPut)insertion).addObserver(file);
+                       for(final Iterator it = files.iterator();
+                           it.hasNext();) {

-                       target.addFile(file);
+                               final java.io.File ioFile = 
(java.io.File)it.next();

+                               try {
+                                       selectSt.setInt(1, target.getId());
+                                       selectSt.setString(2, ioFile.getName());
+
+                                       ResultSet set = selectSt.executeQuery();
+
+                                       if (set.next()) {
+                                               /* this file is already in the 
index */
+                                               continue;
+                                       }
+
+
+                                       FCPTransferQuery insertion = null;
+
+                                       if(insert) {
+                                               insertion = new 
FCPClientPut(ioFile, 0, 0, null,
+                                                                    null, 
FCPClientPut.DEFAULT_INSERTION_PRIORITY,
+                                                                            
true, 0, false);
+                                               
queueManager.addQueryToThePendingQueue(insertion);
+                                       } else {
+                                               insertion = new 
FCPClientPut(ioFile, 0, 0, null,
+                                                                            
null, FCPClientPut.DEFAULT_INSERTION_PRIORITY,
+                                                                            
true, 2, true); /* getCHKOnly */
+                                               
queueManager.addQueryToTheRunningQueue(insertion);
+                                       }
+
+
+                                       st.setInt(1, nextId);
+                                       st.setString(2, ioFile.getName());
+                                       st.setString(3, ioFile.getName() /* 
stand as public key for the moment */);
+                                       st.setString(4, 
ioFile.getAbsolutePath());
+                                       st.setString(5, 
thaw.plugins.insertPlugin.DefaultMIMETypes.guessMIMEType(ioFile.getName()));
+                                       st.setLong(6, ioFile.length());
+                                       st.setNull(7 /* category */, 
Types.INTEGER /* not used at the moment */);
+                                       st.setInt(8, target.getId());
+
+                                       st.execute();
+
+                                       File file = new File(db, nextId);
+
+                                       
((Observable)insertion).addObserver(file);
+
+                                       nextId++;
+                               } catch(SQLException e) {
+                                       Logger.error(new 
IndexManagementHelper(), "Error while adding file: "+e.toString());
+                               }
+                       }
                }
-       }

+               indexBrowser.getTables().getFileTable().refresh();
+       } /* addFiles() */


+
        public static class KeyAdder extends BasicIndexAction implements 
Runnable, MouseListener {
                private JButton cancelButton = null;
                private JButton okButton = null;
@@ -843,7 +1233,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index) && ((Index)node).isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index) && ((Index)node).isModifiable());
                }

                public void apply() {
@@ -938,14 +1330,51 @@
                if ((target == null) || (keys == null))
                        return;

-               for(final Iterator it = keys.iterator();
-                   it.hasNext();) {
+               Hsqldb db;
+               PreparedStatement st;
+               int nextId;

-                       final String key = (String)it.next();
+               db = indexBrowser.getDb();

-                       final thaw.plugins.index.File file = new 
thaw.plugins.index.File(indexBrowser.getDb(), key, target);
-                       target.addFile(file);
+               synchronized(db.dbLock) {
+                       try {
+                               st = 
db.getConnection().prepareStatement("INSERT INTO files "+
+                                                                        "(id, 
filename, publicKey, localPath, mime, size, category, indexParent) "+
+                                                                        
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+                               nextId = DatabaseManager.getNextId(db, "files");
+
+                               if (nextId < 0)
+                                       return;
+                       } catch(SQLException e) {
+                               Logger.error(new IndexManagementHelper(), 
"Exception while trying to add file: "+e.toString());
+                               return;
+                       }
+
+                       for(final Iterator it = keys.iterator();
+                           it.hasNext();) {
+
+                               final String key = (String)it.next();
+
+                               try {
+                                       st.setInt(1, nextId);
+                                       st.setString(2, 
FreenetURIHelper.getFilenameFromKey(key));
+                                       st.setString(3, key);
+                                       st.setNull(4, Types.VARCHAR /* 
localPath */);
+                                       st.setString(5, 
thaw.plugins.insertPlugin.DefaultMIMETypes.guessMIMEType(FreenetURIHelper.getFilenameFromKey(key)));
+                                       st.setLong(6, 0L);
+                                       st.setNull(7 /* category */, 
Types.INTEGER /* not used at the moment */);
+                                       st.setInt(8, target.getId());
+
+                                       st.execute();
+
+                                       nextId++;
+                               } catch(SQLException e) {
+                                       Logger.error(new 
IndexManagementHelper(), "Error while adding file: "+e.toString());
+                               }
+                       }
                }
+
+               indexBrowser.getTables().getFileTable().refresh();
        }


@@ -957,7 +1386,9 @@

                public void setTarget(final IndexTreeNode node) {
                        super.setTarget(node);
-                       getActionSource().setEnabled((node != null) && (node 
instanceof Index) && ((Index)node).isModifiable());
+
+                       if (getActionSource() != null)
+                               getActionSource().setEnabled((node != null) && 
(node instanceof Index) && ((Index)node).isModifiable());
                }

                public void apply() {
@@ -974,8 +1405,32 @@
                if ((target == null) || (linkKey == null))
                        return;

-               final Link newLink = new Link(indexBrowser.getDb(), linkKey, 
target);
-               target.addLink(newLink);
+               Hsqldb db = indexBrowser.getDb();
+
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;
+
+                               int nextId = DatabaseManager.getNextId(db, 
"links");
+
+                               st = 
db.getConnection().prepareStatement("INSERT INTO links (id, publicKey, mark, 
comment, indexParent, indexTarget) "+
+                                                                        
"VALUES (?, ?, ?, ?, ?, ?)");
+
+                               st.setInt(1, nextId);
+                               st.setString(2, linkKey);
+                               st.setInt(3, 0 /* mark : not used at the moment 
*/);
+                               st.setString(4, "" /* comment : not used at the 
moment */);
+                               st.setInt(5, target.getId());
+                               st.setNull(6, Types.INTEGER /* indexTarget : 
not used at the moment */);
+
+                               st.execute();
+                       } catch(SQLException e) {
+                               Logger.error(new IndexManagementHelper(), 
"Error while adding link: "+e.toString());
+                       }
+               }
+
+               indexBrowser.getTables().getLinkTable().refresh();
        }

+
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexProgressBar.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexProgressBar.java        
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexProgressBar.java        
2007-01-25 07:03:17 UTC (rev 11613)
@@ -8,17 +8,16 @@
 import java.util.Observable;
 import java.util.Observer;

+import thaw.core.Logger;
 import thaw.fcp.FCPTransferQuery;

-public class IndexProgressBar implements Observer {
+public class IndexProgressBar {

        private JProgressBar progressBar;

        private int total;
-       private int offset;
        private int current;

-       private Vector transfers;
        private int nmbTransfers;

        public IndexProgressBar() {
@@ -26,55 +25,41 @@
                total = 0;
                current = 0;
                nmbTransfers = 0;
-               offset = 0;
-               transfers = new Vector();
                refreshBar();
                progressBar.setStringPainted(true);
        }

-       public void addTransfer(FCPTransferQuery query) {
-               if (!(query instanceof Observable))
-                       return;
+       public void addTransfer(int nmb) {
+               Logger.info(this, "Adding "+Integer.toString(nmb)+" transfers");

-               ((Observable)query).addObserver(this);
+               total += nmb;
+               current += 0;
+               nmbTransfers += nmb;

-               total += 100;
-               current += query.getProgression();
-               nmbTransfers++;
-               transfers.add(query);
-
                refreshBar();
        }

-       /**
-        * Is usually called automatically
-        */
-       public void removeTransfer(FCPTransferQuery query) {
-               if (!(query instanceof Observable))
-                       return;

-               ((Observable)query).deleteObserver(this);
+       public void removeTransfer(int nmb) {
+               Logger.info(this, "Removing "+Integer.toString(nmb)+" 
transfers");

-               nmbTransfers--;
+               nmbTransfers -= nmb;

-               if (nmbTransfers == 0) {
+               if (nmbTransfers <= 0) {
                        total = 0;
                        current = 0;
-                       offset = 0;
                }
                else {
-                       offset += 100;
+                       current++;
                }

-               transfers.remove(query);
-
                refreshBar();
        }

        public void refreshBar() {
                int pourcent;

-               if (total == 0 || current == total) {
+               if (total == 0) {
                        progressBar.setValue(0);
                        progressBar.setString("");
                } else {
@@ -84,25 +69,6 @@
                }
        }

-       public void update(Observable o, Object arg) {
-               if (o instanceof FCPTransferQuery) {
-                       FCPTransferQuery query = (FCPTransferQuery)o;
-
-                       current = offset;
-                       total = offset;
-
-                       for (Iterator it = transfers.iterator();
-                            it.hasNext(); ) {
-                               FCPTransferQuery q = 
(FCPTransferQuery)it.next();
-                               current += q.getProgression();
-                               total += 100;
-                       }
-
-                       if (query.isFinished())
-                               removeTransfer(query);
-               }
-       }
-
        public JProgressBar getProgressBar() {
                return progressBar;
        }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexRoot.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexRoot.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexRoot.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -5,48 +5,56 @@
 import thaw.fcp.FCPQueueManager;
 import thaw.plugins.Hsqldb;

+import java.sql.*;

-public class IndexRoot extends IndexCategory {
+public class IndexRoot extends IndexFolder implements IndexTreeNode {

        private FCPQueueManager queueManager;
        private IndexBrowserPanel indexBrowser;

        public IndexRoot(final FCPQueueManager queueManager, final 
IndexBrowserPanel indexBrowser, final String name) {
-               super(queueManager, indexBrowser, -1, null, name);
+               super(indexBrowser.getDb(), -1);
                this.queueManager = queueManager;
                this.indexBrowser = indexBrowser;
        }


-       public IndexCategory getNewImportFolder() {
-               int idx;
-               String name;
-               IndexTreeNode node;
-               IndexCategory importFolder;
+       public IndexFolder getNewImportFolder(Hsqldb db) {
+               String fname = null;

-               if (!areChildrenLoaded())
-                       loadChildren();
-
-               /* TODO : Don't use getDirectChild()
+               /* TODO : Don't do like this
                 *        Use the database :
                 *            ask '[importedFolderName]%' ORDER BY name DESC 
LIMIT 1
                 *        and pray there is no importedFolder n??10 or more,
                 *        or that the database will return the good one :p
                 */

-               idx = 0;
-               name = I18n.getMessage("thaw.plugin.index.importedFolderName");
-               node = getDirectChild(name);
+               synchronized(db.dbLock) {
+                       try {
+                               int i;
+                               PreparedStatement select;

-               while (node != null) {
-                       idx++;
-                       name = 
I18n.getMessage("thaw.plugin.index.importedFolderName") + " - 
"+Integer.toString(idx);
-                       node = getDirectChild(name);
+                               select = 
db.getConnection().prepareStatement("SELECT id from indexfolders where parent 
is null and name = ? LIMIT 1");
+
+                               for (i = 0 ; i < 100 ; i++) {
+                                       fname = 
I18n.getMessage("thaw.plugin.index.importedFolderName")+" - 
"+Integer.toString(i);
+                                       select.setString(1, fname);
+
+                                       ResultSet set = select.executeQuery();
+
+                                       if (!set.next())
+                                               break;
+                               }
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to find a name for 
the import folder !");
+                               return null;
+                       }
                }

-               importFolder = 
IndexManagementHelper.addIndexCategory(queueManager, indexBrowser, this, name);
+               if (fname == null)
+                       return null;

-               return importFolder;
+               return IndexManagementHelper.addIndexFolder(indexBrowser, this, 
fname);
        }

 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -21,6 +21,7 @@
 import javax.swing.JPopupMenu;
 import javax.swing.JScrollPane;
 import javax.swing.JTree;
+import javax.swing.tree.MutableTreeNode;
 import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.DefaultTreeCellRenderer;
 import javax.swing.tree.DefaultTreeModel;
@@ -41,7 +42,7 @@
 /**
  * Manages the index tree and its menu (right-click).
  */
-public class IndexTree extends java.util.Observable implements MouseListener, 
ActionListener, java.util.Observer, javax.swing.event.TreeSelectionListener {
+public class IndexTree extends java.util.Observable implements MouseListener, 
ActionListener, javax.swing.event.TreeSelectionListener {

        public final static Color SELECTION_COLOR = new Color(190, 190, 190);
        public final static Color LOADING_COLOR = new Color(230, 230, 230);
@@ -95,8 +96,9 @@
        private Vector toolbarActions;


-       private Hashtable registeredIndexes; /* currently, equals to all the 
indexes, but later, will be == to only the displayed indexes */
+       private Vector updatingIndexes;

+
        /**
         * @param queueManager Not used if selectionOnly is set to true
         * @param config Not used if selectionOnly is set to true (used for 
lastDestinationDirectory and lastSourceDirectory)
@@ -105,19 +107,16 @@
                         final FCPQueueManager queueManager,
                         final IndexBrowserPanel indexBrowser,
                         final Config config) {
+               updatingIndexes = new Vector();
+
                this.queueManager = queueManager;
                this.selectionOnly = selectionOnly;

                panel = new JPanel();
                panel.setLayout(new BorderLayout(10, 10));

-               registeredIndexes = new Hashtable();
-
                root = new IndexRoot(queueManager, indexBrowser, rootName);
-               root.loadChildren();

-               root.addObserver(this);
-
                treeModel = new DefaultTreeModel(root);

                if (!selectionOnly) {
@@ -154,15 +153,19 @@

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.downloadIndexes"));
                indexCategoryMenu.add(item);
-               indexCategoryActions.add(new 
IndexManagementHelper.IndexDownloader(item));
+               indexCategoryActions.add(new 
IndexManagementHelper.IndexDownloader(queueManager, indexBrowser, item));

+               item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.markAllAsSeen"));
+               indexCategoryMenu.add(item);
+               indexCategoryActions.add(new 
IndexManagementHelper.IndexHasChangedFlagReseter(indexBrowser, item));
+
                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.addAlreadyExistingIndex"));
                indexCategoryMenu.add(item);
                indexCategoryActions.add(new 
IndexManagementHelper.IndexReuser(queueManager, indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.addCategory"));
                indexCategoryMenu.add(item);
-               indexCategoryActions.add(new 
IndexManagementHelper.IndexCategoryAdder(queueManager, indexBrowser, item));
+               indexCategoryActions.add(new 
IndexManagementHelper.IndexFolderAdder(indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.createIndex"));
                indexCategoryMenu.add(item);
@@ -184,11 +187,11 @@
                // Index menu
                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.downloadIndex"));
                indexMenu.add(item);
-               indexAndFileActions.add(new 
IndexManagementHelper.IndexDownloader(item));
+               indexAndFileActions.add(new 
IndexManagementHelper.IndexDownloader(queueManager, indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.insertIndex"));
                indexMenu.add(item);
-               indexAndFileActions.add(new 
IndexManagementHelper.IndexUploader(item));
+               indexAndFileActions.add(new 
IndexManagementHelper.IndexUploader(queueManager, indexBrowser, item));

                item = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.rename"));
                indexMenu.add(item);
@@ -261,14 +264,14 @@

                button = new JButton(IconBox.refreshAction);
                
button.setToolTipText(I18n.getMessage("thaw.plugin.index.downloadIndexes"));
-               action = new IndexManagementHelper.IndexDownloader(button);
+               action = new 
IndexManagementHelper.IndexDownloader(queueManager, indexBrowser, button);
                action.setTarget(getRoot());
                toolbarModifier.addButtonToTheToolbar(button);
                toolbarActions.add(action);

                button = new JButton(IconBox.folderNew);
                
button.setToolTipText(I18n.getMessage("thaw.plugin.index.addCategory"));
-               action = new 
IndexManagementHelper.IndexCategoryAdder(queueManager, indexBrowser, button);
+               action = new 
IndexManagementHelper.IndexFolderAdder(indexBrowser, button);
                action.setTarget(getRoot());
                toolbarModifier.addButtonToTheToolbar(button);
                toolbarActions.add(action);
@@ -317,15 +320,8 @@
                action.setTarget(getRoot());
                toolbarModifier.addButtonToTheToolbar(button);
                toolbarActions.add(action);
-
        }

-       /**
-        * called by the index browser, you shouldn't have to bother about it
-        */
-       public void makeFlatList() {
-               root.register();
-       }


        /**
@@ -350,7 +346,7 @@
                if(path == null)
                        return;

-               selectedNode = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+               selectedNode = (IndexTreeNode)(path.getLastPathComponent());


                // Update toolbar
@@ -416,7 +412,7 @@
                        if(selectedNode == null)
                                return;

-                       if(selectedNode instanceof IndexCategory) {
+                       if(selectedNode instanceof IndexFolder) {
                                updateMenuState(selectedNode);
                                indexCategoryMenu.show(e.getComponent(), 
e.getX(), e.getY());
                        }
@@ -434,10 +430,20 @@
                if(path == null)
                        return;

-               selectedNode = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+               selectedNode = (IndexTreeNode)(path.getLastPathComponent());

-               if ((indexBrowser != null) && (selectedNode instanceof Index)) {
-                       
indexBrowser.getUnknownIndexList().addLinks(((Index)selectedNode));
+               if (selectedNode != null) {
+                       if ((indexBrowser != null) && (selectedNode instanceof 
Index)) {
+                               
indexBrowser.getUnknownIndexList().addLinks(((Index)selectedNode));
+                       }
+
+                       if (selectedNode instanceof Index) {
+                               if (((Index)selectedNode).hasChanged()) {
+                                       
((Index)selectedNode).setHasChangedFlag(false);
+                                       redraw(path);
+                               }
+                       }
+
                }

                setChanged();
@@ -467,25 +473,68 @@
                        selectedNode = root;
        }

-       public void save() {
-               root.save();
+
+       private boolean forceHasChangedFlagReload = false;
+
+
+       public void refresh() {
+               refresh(((IndexTreeNode)null));
        }


-       public void update(final java.util.Observable o, final Object param) {
-               if( (o instanceof Index)
-                   && (param == null) ) {
-                       final Index index = (Index)o;
+       public void refresh(IndexTreeNode node) {
+               forceHasChangedFlagReload = true;
+               if (treeModel != null) {
+                       if (node != null && node.isInTree())
+                               treeModel.reload(node.getTreeNode());
+                       else
+                               treeModel.reload(getRoot().getTreeNode());
+               }
+               forceHasChangedFlagReload = false;
+       }

-                       if (treeModel != null) {
-                               treeModel.nodeChanged(index.getTreeNode());
-                               if(index.getTreeNode().getParent() != null)
-                                       
treeModel.nodeChanged(index.getTreeNode().getParent());
+
+       public void refresh(TreePath path) {
+               refresh();
+       }
+
+
+       public void redraw() {
+               redraw((IndexTreeNode)null);
+       }
+
+       public void redraw(IndexTreeNode node, boolean parents) {
+               if (!parents)
+                       redraw(node);
+               else {
+                       while (node != null) {
+                               redraw(node);
+                               node = 
((IndexTreeNode)(((MutableTreeNode)node).getParent()));
                        }
                }
        }

+       public void redraw(IndexTreeNode node) {
+               //refresh(node);
+               forceHasChangedFlagReload = true;
+               if (treeModel != null) {
+                       if (node != null && node.isInTree())
+                               treeModel.nodeChanged(node.getTreeNode());
+                       else
+                               treeModel.nodeChanged(getRoot().getTreeNode());
+               }
+               forceHasChangedFlagReload = false;
+       }

+       public void redraw(TreePath path) {
+               Object[] nodes = (Object[])(path.getPath());
+
+               for (int i = 0 ; i < nodes.length ; i++) {
+                       IndexTreeNode node = (IndexTreeNode)nodes[i];
+                       redraw(node);
+               }
+       }
+
        public class IndexTreeRenderer extends DefaultTreeCellRenderer {

                private static final long serialVersionUID = 1L;
@@ -504,13 +553,18 @@
                        setBackgroundNonSelectionColor(Color.WHITE);
                        setBackgroundSelectionColor(IndexTree.SELECTION_COLOR);

-                       if(value instanceof DefaultMutableTreeNode) {
-                               final Object o = 
((DefaultMutableTreeNode)value).getUserObject();
+                       if(value instanceof DefaultMutableTreeNode || value 
instanceof IndexTreeNode) {
+                               Object o;

+                               if (value instanceof DefaultMutableTreeNode)
+                                       o = 
((DefaultMutableTreeNode)value).getUserObject();
+                               else
+                                       o = value;
+
                                if(o instanceof Index) {
                                        final Index index = (Index)o;

-                                       if (index.isUpdating()) {
+                                       if (isIndexUpdating(index)) {
                                                
setBackgroundNonSelectionColor(IndexTree.LOADING_COLOR);
                                                
setBackgroundSelectionColor(IndexTree.LOADING_SELECTION_COLOR);
                                        }
@@ -527,6 +581,10 @@
                                        /* Remember that for the index category,
                                           this kind of query is recursive */
                                        boolean modifiable = 
((IndexTreeNode)o).isModifiable();
+
+                                       if (forceHasChangedFlagReload)
+                                               
((IndexTreeNode)o).forceHasChangedReload();
+
                                        boolean hasChanged = 
((IndexTreeNode)o).hasChanged();

                                        int style = 0;
@@ -556,16 +614,16 @@


        public boolean addToRoot(final IndexTreeNode node) {
-               return addToIndexCategory(root, node);
+               return addToIndexFolder(root, node);
        }

-       public boolean addToIndexCategory(final IndexCategory target, final 
IndexTreeNode node) {
+       public boolean addToIndexFolder(final IndexFolder target, final 
IndexTreeNode node) {
                if ((node instanceof Index) && 
alreadyExistingIndex(node.getPublicKey())) {
                        Logger.notice(this, "Index already added");
                        return false;
                }

-               node.setParent(target);
+               node.setParent(target.getId());
                target.getTreeNode().insert(node.getTreeNode(), 
target.getTreeNode().getChildCount());
                treeModel.reload(target);

@@ -614,30 +672,28 @@
        /**
         * @param node can be null
         */
-       public void reloadModel(final DefaultMutableTreeNode node) {
+       public void reloadModel(final MutableTreeNode node) {
                treeModel.reload(node);
        }

+
        public void reloadModel() {
                treeModel.reload();
        }


-       public void registerIndex(Index index) {
-               if (index.getPublicKey() == null) {
-                       Logger.warning(this, "Hu ?! no key for index 
'"+index.toString()+"' ?");
-                       return;
-               }
+       /* TODO : Improve this ; quite ugly */

-               
registeredIndexes.put(FreenetURIHelper.getComparablePart(index.getPublicKey()),
-                                     index);
+
+       public void addUpdatingIndex(Index index) {
+               updatingIndexes.add(new Integer(index.getId()));
        }

-       public void unregisterIndex(Index index) {
-               
registeredIndexes.remove(FreenetURIHelper.getComparablePart(index.getPublicKey()));
+       public void removeUpdatingIndex(Index index) {
+               updatingIndexes.remove(new Integer(index.getId()));
        }

-       public Index getRegisteredIndex(String key) {
-               return 
((Index)registeredIndexes.get(FreenetURIHelper.getComparablePart(key)));
+       public boolean isIndexUpdating(Index index) {
+               return (updatingIndexes.indexOf(new Integer(index.getId())) >= 
0);
        }
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java   2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java   2007-01-25 
07:03:17 UTC (rev 11613)
@@ -2,27 +2,34 @@

 import java.util.Vector;

+import java.util.Observable;
+import java.util.Observer;
+
 import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
 import org.w3c.dom.Element;
 import org.w3c.dom.Document;


+import thaw.fcp.FCPQueueManager;
+
 public interface IndexTreeNode {

-       public DefaultMutableTreeNode getTreeNode();
+       public MutableTreeNode getTreeNode();

-       public void setParent(IndexCategory parent);
+       public void setParent(int id);

        /**
-        * get Id of this node in the database.
+        * Allow to know if it's a dumb node or a real one in the tree
         */
-       public int getId();
+       public boolean isInTree();

        /**
-        * Insert the node in the database.
+        * get Id of this node in the database.
         */
-       public boolean create();
+       public int getId();

+
        /**
         * Change the name of the node.
         */
@@ -34,49 +41,34 @@
        public void delete();

        /**
-        * Update from freenet / Update the freenet version, depending of the 
index kind (recursive)
+        * Get key(s)
         */
-       public void update();
+       public String getPublicKey();
+       public String getPrivateKey();

-       /**
-        * Update from freenet using the given revision
-        * @param rev -1 means the lastest
-        */
-       public void updateFromFreenet(int rev);
+       public boolean isModifiable();
+       public boolean hasChanged();
+       public boolean setHasChangedFlag(boolean flag);

-       public boolean isUpdating();
-
        /**
-        * Save the state in the database (recursive).
+        * for internal use only !
         */
-       public void save();
+       public boolean setHasChangedFlagInMem(boolean flag);

        /**
-        * Get key(s)
+        * Will export private keys too !
         */
-       public String getPublicKey();
-       public String getPrivateKey();
+       public Element do_export(Document xmlDoc, boolean withContent);
+       public void do_import(IndexBrowserPanel indexBrowser, Element e);

-       public Vector getIndexIds();

        /**
-        * All the indexes !
+        * @return the number of transfer started
         */
-       public Vector getIndexes();
+       public int insertOnFreenet(Observer o, IndexTree indexTree, 
FCPQueueManager queueManager);
+       public int downloadFromFreenet(Observer o, IndexTree indexTree, 
FCPQueueManager queueManager);
+       public int downloadFromFreenet(Observer o, IndexTree indexTree, 
FCPQueueManager queueManager, int rev);

-       public Index getIndex(int id);

-       public void addObserver(java.util.Observer o);
-
-       public boolean isModifiable();
-       public boolean hasChanged();
-
-       public void register();
-       public void unregister();
-
-       /**
-        * Will export private keys too !
-        */
-       public Element do_export(Document xmlDoc, boolean withContent);
-       public void do_import(Element e);
+       public void forceHasChangedReload();
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/Link.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Link.java    2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Link.java    2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -9,81 +9,90 @@
 import org.w3c.dom.Element;

 import thaw.core.Logger;
+import thaw.core.FreenetURIHelper;
 import thaw.plugins.Hsqldb;

 public class Link extends java.util.Observable {
        private int id;
+       private final Hsqldb db;

-       private String indexName;
-       private String key;
+       private String publicKey;

-       private Index parent = null;
        private int parentId;

-       private final Hsqldb db;
+       public Link(final Hsqldb hsqldb, final int id) {
+               this.id = id;
+               this.db = hsqldb;

-
-       public Link(final Hsqldb hsqldb, final String indexName, final String 
key, final Index parent) {
-               this.indexName = indexName;
-               if (key != null)
-                       this.key = key.trim();
-               else
-                       this.key = null;
-               this.parent = parent;
-               db = hsqldb;
+               reloadDataFromDb(id);
        }

-       public Link(final Hsqldb hsqldb, final String key, final Index parent) {
-               this(hsqldb, Index.getNameFromKey(key), key, parent);
+       public Link(final Hsqldb hsqldb, final int id, String publicKey,
+                   int parentId) {
+               this.id = id;
+               this.db = hsqldb;
+               this.publicKey = publicKey;
+               this.parentId = parentId;
        }

-       public Link(final Hsqldb hsqldb, final ResultSet resultSet, final Index 
parent) throws SQLException {
-               db = hsqldb;
-               id = resultSet.getInt("id");
-               key = resultSet.getString("publicKey").trim();
+       public void reloadDataFromDb(int id) {
+               this.id = id;

-               indexName = Index.getNameFromKey(key);
+               try {
+                       PreparedStatement st;

-               this.parent = parent;
-               if (parent != null)
-                       parentId = parent.getId();
-               else
-                       parentId = resultSet.getInt("indexParent");
-       }
+                       st = db.getConnection().prepareStatement("SELECT 
publicKey, indexParent FROM links "+
+                                                                "WHERE id = ? 
LIMIT 1");

-       public Link(final Hsqldb hsqldb, final Element linkElement, final Index 
parent) {
-               db = hsqldb;
-               key = linkElement.getAttribute("key");
+                       st.setInt(1, id);

-               if (key != null)
-                       key = key.trim();
+                       ResultSet rs = st.executeQuery();

-               indexName = Index.getNameFromKey(key);
-
-               this.parent = parent;
-
-               if (parent != null)
-                       parentId = parent.getId();
-               else
-                       parentId = -1;
+                       if (rs.next()) {
+                               publicKey = rs.getString("publicKey");
+                               parentId = rs.getInt("indexParent");
+                       } else {
+                               Logger.error(this, "Link 
'"+Integer.toString(id)+"' not found.");
+                       }
+               } catch(SQLException e) {
+                       Logger.error(this, "Error while loading data for link 
'"+Integer.toString(id)+"': "+e.toString());
+               }
        }

        public String getPublicKey() {
-               return key;
+               if (publicKey == null)
+                       reloadDataFromDb(id);
+
+               return publicKey;
        }

        public boolean compare(final Link l) {
+               String key_a;
+               String key_b;
+
+               key_a = getPublicKey();
+               key_b = l.getPublicKey();
+
                if ((l == null)
-                   || (getPublicKey() == null)
-                   || (l.getPublicKey() == null)
-                   || (getPublicKey().length() < 40)
-                   || (l.getPublicKey().length() < 40))
+                   || (key_a == null)
+                   || (key_b == null)
+                   || (key_a.length() < 40)
+                   || (key_b.length() < 40))
                        return false;

-               return (l.getPublicKey().substring(4, 
40).equals(getPublicKey().substring(4, 40)));
+               key_a = FreenetURIHelper.getComparablePart(key_a);
+               key_b = FreenetURIHelper.getComparablePart(key_b);
+
+               return (key_a.equals(key_b));
        }

        public boolean compare(final Index l) {
+               String key_a;
+               String key_b;
+
+               key_a = getPublicKey();
+               key_b = l.getPublicKey();
+
                if ((l == null)
                    || (getPublicKey() == null)
                    || (l.getPublicKey() == null)
@@ -91,111 +100,79 @@
                    || (l.getPublicKey().length() < 40))
                        return false;

-               return (l.getPublicKey().substring(4, 
40).equals(getPublicKey().substring(4, 40)));
+               key_a = FreenetURIHelper.getComparablePart(key_a);
+               key_b = FreenetURIHelper.getComparablePart(key_b);
+
+               return (key_a.equals(key_b));
+
        }

        public void setParent(final Index index) {
-               parent = index;
+               try {
+                       PreparedStatement st;
+
+                       st = db.getConnection().prepareStatement("UPDATE links 
SET indexParent = ? "+
+                                                                "WHERE id = 
?");
+                       st.setInt(1, index.getId());
+                       st.setInt(2, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to set parent because: 
"+e.toString());
+               }
        }

        public Index getParent() {
-               return parent;
+               int parentId;
+
+               parentId = getParentId();
+
+               if (parentId < 0)
+                       return null;
+
+               return new Index(db, parentId);
        }

        public int getParentId() {
-               if (parent != null)
-                       return parent.getId();
-
                return parentId;
        }

        public String getIndexName() {
-               return indexName;
-       }
+               String name;

-       public String toString() {
-               return getIndexName();
-       }
+               if (publicKey == null)
+                       reloadDataFromDb(id);

-       public void setIndexKey(final String key) {
-               this.key = key;
+               name = Index.getNameFromKey(publicKey);

-               if (this.key != null)
-                       this.key = this.key.trim();
-
-               setChanged();
-               this.notifyObservers();
+               return name;
        }

-       public void insert() {
-               try {
-                       PreparedStatement st;
-
-                       synchronized (db.dbLock) {
-                               st = 
db.getConnection().prepareStatement("SELECT id FROM links ORDER BY id DESC 
LIMIT 1");
-
-                               try {
-                                       if(st.execute()) {
-                                               final ResultSet result = 
st.getResultSet();
-                                               result.next();
-                                               id = result.getInt("id")+1;
-                                       } else
-                                               id = 1;
-                               } catch(final SQLException e) {
-                                       id = 1;
-                               }
-
-                               st = 
db.getConnection().prepareStatement("INSERT INTO links (id, publicKey, "+
-                                               "mark, comment, indexParent, 
indexTarget) "+
-                               "VALUES (?, ?, ?, ?, ?, ?)");
-                               st.setInt(1, id);
-
-                               if(key != null)
-                                       st.setString(2, key);
-                               else
-                                       st.setString(2, indexName);
-
-                               st.setInt(3, 0);
-                               st.setString(4, "No comment");
-                               st.setInt(5, parent.getId());
-                               st.setNull(6, Types.INTEGER);
-
-                               st.execute();
-                       }
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to insert link to 
'"+indexName+"' because: "+e.toString());
-               }
+       /**
+        * return the index name
+        */
+       public String toString() {
+               return getIndexName();
        }

-       public boolean isInTheDatabase() {
-               if (parent == null) {
-                       Logger.notice(this, "isInTheDatabase(): No parent !");
-                       return false;
-               }
+       public void setPublicKey(final String key) {
+               this.publicKey = key;

                try {
                        PreparedStatement st;

-                       st = db.getConnection().prepareStatement("SELECT 
publicKey from links WHERE publicKey = ? AND indexParent = ?");
-
+                       st = db.getConnection().prepareStatement("UPDATE links 
SET publicKey = ? "+
+                                                                "WHERE id = 
?");
                        st.setString(1, key);
-
-                       st.setInt(2, getParent().getId());
-
-                       if(st.execute()) {
-                               final ResultSet result = st.getResultSet();
-                               if ((result != null) && result.next())
-                                       return true;
-                       }
-
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to check if link '"+key+"' 
exists because: "+e.toString());
+                       st.setInt(2, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Error while changing publicKey: 
"+e.toString());
                }
-
-               return false;
        }

-
+       /**
+        * database related
+        */
        public void delete() {
                try {
                        PreparedStatement st;
@@ -206,44 +183,30 @@
                        st.execute();

                } catch(final SQLException e) {
-                       Logger.error(this, "Unable to remove link to 
'"+indexName+"' because: "+e.toString());
+                       Logger.error(this, "Unable to remove link because: 
"+e.toString());
                }
        }

-       public void update() {
-               try {
-                       PreparedStatement st;

-                       st = db.getConnection().prepareStatement("UPDATE links 
SET publicKey = ?, indexParent = ? WHERE id = ?");

-                       if(key != null)
-                               st.setString(1, key);
-                       else
-                               st.setString(1, indexName);
-
-                       st.setInt(2, getParent().getId());
-
-                       st.setInt(3, id);
-
-                       st.execute();
-               } catch(final SQLException e) {
-                       Logger.error(this, "Unable to update link to 
'"+indexName+"' because: "+e.toString());
-               }
-       }
-
-
        public Element getXML(final Document xmlDoc) {
                final Element link = xmlDoc.createElement("index");

-               link.setAttribute("key", key);
+               link.setAttribute("key", getPublicKey());

                return link;
        }


+       /**
+        * do a sql queries !
+        */
        public boolean isModifiable() {
-               if (getParent() == null)
+               Index index = getParent();
+
+               if (index == null)
                        return false;
-               return getParent().isModifiable();
+
+               return index.isModifiable();
        }
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/LinkList.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/LinkList.java        2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/LinkList.java        2007-01-25 
07:03:17 UTC (rev 11613)
@@ -4,14 +4,6 @@

 public interface LinkList {

-       public void loadLinks(String columnToSort, boolean asc);
+       public Vector getLinkList(String columnToSort, boolean asc);

-       public Vector getLinkList();
-
-       public Link getLink(int index);
-
-       /**
-        * Can update the database.
-        */
-       public void unloadLinks();
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/LinkManagementHelper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/LinkManagementHelper.java    
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/LinkManagementHelper.java    
2007-01-25 07:03:17 UTC (rev 11613)
@@ -25,11 +25,13 @@


        public static class LinkRemover implements LinkAction {
+               private IndexBrowserPanel indexBrowser;
                private AbstractButton actionSource;
                private Vector target;

-               public LinkRemover(final AbstractButton actionSource) {
+               public LinkRemover(IndexBrowserPanel indexBrowser, final 
AbstractButton actionSource) {
                        this.actionSource = actionSource;
+                       this.indexBrowser = indexBrowser;
                        if (actionSource != null)
                                actionSource.addActionListener(this);
                }
@@ -41,41 +43,35 @@

                        this.target = target;

-                       if (target != null) {
-                               for (final Iterator it = target.iterator();
-                                    it.hasNext();) {
-                                       final Link link = (Link)it.next();
-
-                                       if (!link.isModifiable()) {
-                                               isOk = false;
-                                               break;
-                                       }
-                               }
+                       if (target != null && target.size() > 0) {
+                               Link link = (Link)target.get(0);
+                               if (!link.isModifiable())
+                                       isOk = false;
                        }

-
-                       actionSource.setEnabled((target != null) && 
(target.size() != 0) && isOk);
+                       actionSource.setEnabled((target != null) && 
(target.size() > 0) && isOk);
                }

                public void actionPerformed(final ActionEvent e) {
-                       LinkManagementHelper.removeLinks(target);
+                       LinkManagementHelper.removeLinks(indexBrowser, target);
                }
        }

-
-       public static void removeLinks(final Vector links) {
+       public static void removeLinks(IndexBrowserPanel indexBrowser, final 
Vector links) {
                if (links == null)
                        return;

                for (final Iterator it = links.iterator();
                     it.hasNext() ; ) {
                        final Link link = (Link)it.next();
-                       link.getParent().removeLink(link);
+                       link.delete();
                }
+
+               indexBrowser.getTables().getLinkTable().refresh();
        }


-       public static class IndexAdder implements LinkAction {
+       public static class IndexAdder implements LinkAction, Runnable {
                private FCPQueueManager queueManager;
                private IndexBrowserPanel indexBrowser;

@@ -98,11 +94,19 @@
                }

                public void actionPerformed(final ActionEvent e) {
+                       Thread adder = new Thread(this);
+                       adder.start();
+               }
+
+
+               public void run() {
                        for (final Iterator it = t.iterator();
                             it.hasNext(); ) {
                                final Link link = (Link)it.next();
-                               IndexManagementHelper.addIndex(queueManager, 
indexBrowser, null,
-                                                              
link.getPublicKey());
+                               if (link != null) {
+                                       
IndexManagementHelper.addIndex(queueManager, indexBrowser, null,
+                                                                      
link.getPublicKey());
+                               }
                        }
                }
        }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/LinkTable.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/LinkTable.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/LinkTable.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -10,6 +10,8 @@
 import java.util.Iterator;
 import java.util.Observable;
 import java.util.Vector;
+import java.awt.Color;
+import java.awt.Component;

 import javax.swing.JLabel;
 import javax.swing.JMenuItem;
@@ -19,6 +21,7 @@
 import javax.swing.JTable;
 import javax.swing.JButton;
 import javax.swing.event.TableModelEvent;
+import javax.swing.table.DefaultTableCellRenderer;
 import javax.swing.tree.TreePath;

 import thaw.core.I18n;
@@ -55,7 +58,8 @@

                linkListModel = new LinkListModel();
                table = new JTable(linkListModel);
-               table.setShowGrid(true);
+               table.setShowGrid(false);
+               table.setDefaultRenderer(table.getColumnClass(0), new 
LinkRenderer());

                panel = new JPanel();
                panel.setLayout(new BorderLayout());
@@ -92,10 +96,10 @@
                item = new JMenuItem(I18n.getMessage("thaw.common.remove"));
                button = new JButton(IconBox.delete);
                button.setToolTipText(I18n.getMessage("thaw.common.remove"));
-               toolbarActions.add(new 
LinkManagementHelper.LinkRemover(button));
+               toolbarActions.add(new 
LinkManagementHelper.LinkRemover(indexBrowser, button));
                toolbarModifier.addButtonToTheToolbar(button);
                rightClickMenu.add(item);
-               rightClickActions.add(new 
LinkManagementHelper.LinkRemover(item));
+               rightClickActions.add(new 
LinkManagementHelper.LinkRemover(indexBrowser, item));

                gotoItem = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.gotoIndex"));
                rightClickMenu.add(gotoItem);
@@ -135,7 +139,7 @@
        }

        protected Vector getSelectedLinks(final int[] selectedRows) {
-               final Vector srcList = linkList.getLinkList();
+               final Vector srcList = linkList.getLinkList(null, false);
                final Vector links = new Vector();

                for(int i = 0 ; i < selectedRows.length ; i++) {
@@ -147,25 +151,20 @@
        }

        public void setLinkList(final LinkList linkList) {
-               if(this.linkList != null) {
-                       this.linkList.unloadLinks();
-               }
-
-               if(linkList != null) {
-                       linkList.loadLinks(null, true);
-               }
-
                this.linkList = linkList;
+               linkListModel.reloadLinkList(linkList);

-               linkListModel.reloadLinkList(linkList);
+               if (linkList != null)
+                       indexBrowser.getUnknownIndexList().addLinks(linkList);
        }

+       public LinkList getLinkList() {
+               return linkList;
+       }
+
        public void mouseClicked(final MouseEvent e) {
                Vector selection;

-               if (linkList instanceof Index)
-                       ((Index)linkList).setChanged(false);
-
                if (linkList == null) {
                        selectedRows = null;
                        return;
@@ -211,32 +210,15 @@
                        if (selectedRows.length <= 0)
                                return;

-                       final Link link = 
(Link)linkList.getLinkList().get(selectedRows[0]);
+                       /* TODO */

-                       if (link.getParentId() == -1) {
-                               Logger.notice(this, "No parent ? Abnormal !");
-                               return;
-                       }
-
-                       Index parent;
-                       if (link.getParent() == null)
-                               parent = 
indexBrowser.getIndexTree().getRoot().getIndex(link.getParentId());
-                       else
-                               parent = link.getParent();
-
-                       if (parent == null) {
-                               Logger.notice(this, "Cannot find again the 
parent ?! Id: "+Integer.toString(link.getParentId()));
-                               return;
-                       }
-
-                       
indexBrowser.getIndexTree().getTree().setSelectionPath(new 
TreePath(parent.getTreeNode().getPath()));
-
-                       indexBrowser.getTables().setList(parent);
-
                        return;
                }
        }

+       public void refresh() {
+               linkListModel.refresh();
+       }


        public class LinkListModel extends javax.swing.table.AbstractTableModel 
implements java.util.Observer {
@@ -254,35 +236,14 @@
                        columnNames = new Vector();

                        
columnNames.add(I18n.getMessage("thaw.plugin.index.index"));
-                       columnNames.add(I18n.getMessage("thaw.common.key"));
+                       //columnNames.add(I18n.getMessage("thaw.common.key"));
                }

                public void reloadLinkList(final LinkList newLinkList) {
-                       if ((linkList != null) && (linkList instanceof 
Observable)) {
-                               ((Observable)linkList).deleteObserver(this);
-                       }

-                       if ((newLinkList != null) && (newLinkList instanceof 
Observable)) {
-                               ((Observable)newLinkList).addObserver(this);
-                       }
-
                        linkList = newLinkList;
-
-
-                       if(links != null) {
-                               for(final Iterator it = links.iterator();
-                                   it.hasNext(); ) {
-                                       final thaw.plugins.index.Link link = 
(thaw.plugins.index.Link)it.next();
-                                       link.deleteObserver(this);
-                               }
-                       }
-
                        links = null;

-                       if(linkList != null) {
-                               links = linkList.getLinkList();
-                       }
-
                        this.refresh();

                }
@@ -307,15 +268,16 @@

                        switch(column) {
                        case(0): return link.getIndexName();
-                       case(1): return link.getPublicKey();
+                               //case(1): return link.getPublicKey();
                        default: return null;
                        }
                }

                public void refresh() {
                        if(linkList != null) {
-                               links = linkList.getLinkList();
-                       }
+                               links = linkList.getLinkList(null, false);
+                       } else
+                               links = null;

                        final TableModelEvent event = new TableModelEvent(this);
                        this.refresh(event);
@@ -341,5 +303,44 @@
                }
        }

+
+       private class LinkRenderer extends DefaultTableCellRenderer {
+               private final static long serialVersionUID = 20060821;
+
+               private Color softGray;
+
+               public LinkRenderer() {
+                       softGray = new Color(240,240,240);
+               }
+
+               public Component getTableCellRendererComponent(final JTable 
table, final Object value,
+                                                              final boolean 
isSelected, final boolean hasFocus,
+                                                              final int row, 
final int column) {
+
+                       if(value == null)
+                               return 
super.getTableCellRendererComponent(table, "",
+                                                                          
isSelected, hasFocus, row, column);
+
+                       Component cell;
+
+                       if(value instanceof Long)
+                               cell = 
super.getTableCellRendererComponent(table,
+                                                                          
thaw.plugins.queueWatcher.QueueTableModel.getPrintableSize(((Long)value).longValue()),
+                                                                          
isSelected, hasFocus, row, column);
+                       else
+                               cell = 
super.getTableCellRendererComponent(table, value,
+                                                                          
isSelected, hasFocus,
+                                                                          row, 
column);
+                       if (!isSelected) {
+                               if (row % 2 == 0)
+                                       cell.setBackground(Color.WHITE);
+                               else
+                                       cell.setBackground(softGray);
+                       }
+                       return cell;
+               }
+
+       }
+
 }


Modified: trunk/apps/Thaw/src/thaw/plugins/index/SearchBar.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/SearchBar.java       2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/SearchBar.java       2007-01-25 
07:03:17 UTC (rev 11613)
@@ -23,11 +23,8 @@

        private Tables tables;

-       private FCPQueueManager queueManager;
-
-       public SearchBar(final FCPQueueManager queueManager, IndexBrowserPanel 
indexBrowser) {
+       public SearchBar(IndexBrowserPanel indexBrowser) {
                this.indexBrowser = indexBrowser;
-               this.queueManager = queueManager;

                panel = new JPanel();
                panel.setLayout(new BorderLayout(0, 0));
@@ -56,7 +53,9 @@
                userText.setSelectionStart(0);
                userText.setSelectionEnd(userText.getText().length());

-               final SearchResult sr = new SearchResult(indexBrowser.getDb(), 
userText.getText(), indexBrowser.getIndexTree().getSelectedNode(), 
queueManager);
+               final SearchResult sr = new SearchResult(indexBrowser.getDb(),
+                                                        
userText.getText().trim(),
+                                                        
indexBrowser.getIndexTree().getSelectedNode());
                indexBrowser.getTables().setList(sr);
        }


Modified: trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java    2007-01-25 
03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java    2007-01-25 
07:03:17 UTC (rev 11613)
@@ -13,176 +13,115 @@
 import thaw.fcp.FCPQueueManager;
 import thaw.plugins.Hsqldb;

-public class SearchResult extends Observable implements Observer, 
FileAndLinkList {
+public class SearchResult implements FileAndLinkList {

-       private Vector fileList = null;
-       private Vector linkList = null;
+       private String[] search = null;

-       private String[] search      = null;
-       private Vector indexIds = null;
-
        private Hsqldb db;
-       private FCPQueueManager queueManager;
+       private IndexTreeNode node;

-       public SearchResult(final Hsqldb hsqldb, final String search, final 
IndexTreeNode node, final FCPQueueManager queueManager) {
-               this.queueManager = queueManager;
+       public SearchResult(final Hsqldb hsqldb, final String search, final 
IndexTreeNode node) {
                this.search = search.split(" ");
-               if (node == null)
-                       indexIds = null;
-               else
-                       indexIds = node.getIndexIds();
+               this.node = node;
                db = hsqldb;
        }

-       protected PreparedStatement makeSearchQuery(final String fields, final 
String searchField, final String table, final Vector indexIds, final String[] 
searchPatterns,
-                                        final String columnToSort, boolean 
asc) throws SQLException {
-               String query = "";
-               PreparedStatement st;

-               query = "SELECT "+fields+" FROM "+table +" WHERE ";
+       public String getWhereClause(boolean hasFilename) {
+               String where = null;
+               String column = hasFilename ? "filename" : "publicKey";

-               if (indexIds != null) {
-                       query = query +"(FALSE";
-
-                       for (final Iterator it = indexIds.iterator();
-                            it.hasNext();) {
-                               it.next();
-                               query = query + " OR indexParent = ?";
+               if (node instanceof IndexFolder) {
+                       if (node.getId() >= 0) {
+                               where = "indexParent IN "+
+                                       "(SELECT indexParents.indexId FROM 
indexParents WHERE indexParents.folderId = ?)";
                        }
-
-                       query = query + ") AND ";
                }

-               query = query + "(TRUE";
-
-               for (int i = 0 ; i < searchPatterns.length; i++) {
-                       query = query + " AND LOWER("+searchField+") LIKE ?";
+               if (node instanceof Index) {
+                       where = "indexParent = ? ";
                }

-               query = query +")";
-
-               if(columnToSort != null) {
-                       query = query + "ORDER BY " + columnToSort;
-
-                       if(!asc)
-                               query = query + " DESC";
+               for (int i = 0 ; i < search.length ; i++) {
+                       if (where == null) {
+                               where = " LOWER("+column+") LIKE ?";
+                       } else {
+                               where = " AND LOWER("+column+") LIKE ?";
+                       }
                }

-               final Connection c = db.getConnection();
-               st = c.prepareStatement(query);
+               return where;
+       }

-               int i;
+       public void fillInStatement(PreparedStatement st) throws SQLException {
+               if (!(node instanceof IndexFolder) || node.getId() >= 0)
+                       st.setInt(1, node.getId());

-               i = 1;
-
-               if (indexIds != null) {
-                       for (final Iterator it = indexIds.iterator();
-                            it.hasNext(); i++) {
-                               st.setInt(i, ((Integer)it.next()).intValue());
-                       }
+               for (int i = 0 ; i < search.length ; i++) {
+                       st.setString(i+2, "%" + search[i] + "%");
                }
-
-               for (int j = 0 ; j < searchPatterns.length; j++) {
-                       st.setString(i+j, 
"%"+(searchPatterns[j]).toLowerCase()+"%");
-               }
-
-               return st;
        }

-       public void loadFiles(final String columnToSort, final boolean asc) {
-               if (fileList != null) {
-                       Logger.notice(this, "Files already loaded, won't reload 
them");
-                       return;
-               }
+       public Vector getFileList(String col, boolean asc) {

-               fileList = new Vector();
+               Vector v = new Vector();

-               try {
-                       final PreparedStatement st = makeSearchQuery("id, 
filename, publicKey, localPath, mime, size, category, indexParent", "filename",
-                                                              "files", 
indexIds, search, columnToSort, asc);
-                       if (st.execute()) {
-                               final ResultSet results = st.getResultSet();
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

-                               while(results.next()) {
-                                       final thaw.plugins.index.File file = 
new thaw.plugins.index.File(db, results, null);
-                                       file.setTransfer(queueManager);
-                                       file.addObserver(this);
-                                       fileList.add(file);
-                               }
-                       }
-               } catch(final SQLException e) {
-                       Logger.error(this, "Exception while searching: 
"+e.toString());
-               }
+                               st = 
db.getConnection().prepareStatement("SELECT id, filename, publicKey, localPath, 
mime, size, indexParent "+
+                                                                        "FROM 
files "+
+                                                                        "WHERE 
"+getWhereClause(true)+" ORDER by filename");
+                               fillInStatement(st);

-               setChanged();
-               this.notifyObservers();
-       }
+                               ResultSet set = st.executeQuery();

-       public void loadLinks(final String columnToSort, final boolean asc) {
-               if (linkList != null) {
-                       Logger.notice(this, "Links already loaded, won't reload 
them");
-                       return;
-               }
-               linkList = new Vector();
-
-               try {
-                       final PreparedStatement st = makeSearchQuery("id, 
publicKey, mark, comment, indexTarget, indexParent", "publicKey",
-                                                              "links", 
indexIds, search, columnToSort, asc);
-                       if (st.execute()) {
-                               final ResultSet results = st.getResultSet();
-
-                               while(results.next()) {
-                                       final Link link = new Link(db, results, 
null);
-                                       linkList.add(link);
+                               while(set.next()) {
+                                       v.add(new thaw.plugins.index.File(db,
+                                                                         
set.getInt("id"),
+                                                                         
set.getString("filename"),
+                                                                         
set.getString("publicKey"),
+                                                                         new 
java.io.File(set.getString("localPath")),
+                                                                         
set.getString("mime"),
+                                                                         
set.getLong("size"),
+                                                                         
set.getInt("indexParent")));
                                }
+
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while searching: 
"+e.toString());
                        }
-               } catch(final SQLException e) {
-                       Logger.error(this, "Exception while searching: 
"+e.toString());
                }

-               setChanged();
-               this.notifyObservers();
+               return v;
        }

+       public Vector getLinkList(String col, boolean asc) {
+                               Vector v = new Vector();

-       public void update(final Observable o, final Object param) {
-               setChanged();
-               this.notifyObservers(o);
-       }
+               synchronized(db.dbLock) {
+                       try {
+                               PreparedStatement st;

+                               st = 
db.getConnection().prepareStatement("SELECT id, publicKey, indexParent "+
+                                                                        "FROM 
links "+
+                                                                        "WHERE 
"+getWhereClause(false));
+                               fillInStatement(st);
+                               ResultSet set = st.executeQuery();

-       public Vector getFileList() {
-               return fileList;
-       }
+                               while(set.next()) {
+                                       v.add(new Link(db,
+                                                      set.getInt("id"),
+                                                      
set.getString("publicKey"),
+                                                      
set.getInt("indexParent")));
+                               }

-       public Vector getLinkList() {
-               return linkList;
-       }
-
-
-
-       public thaw.plugins.index.File getFile(final int index) {
-               return (thaw.plugins.index.File)fileList.get(index);
-       }
-
-       public Link getLink(final int index) {
-               return (Link)linkList.get(index);
-       }
-
-
-
-       public void unloadFiles() {
-               for (final Iterator it = fileList.iterator();
-                    it.hasNext();) {
-                       final thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
-                       file.deleteObserver(this);
+                       } catch(SQLException e) {
+                               Logger.error(this, "Error while searching: 
"+e.toString());
+                       }
                }

-               fileList = null;
+               return v;
        }

-       public void unloadLinks() {
-               fileList = null;
-       }
-
 }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/Tables.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Tables.java  2007-01-25 03:40:46 UTC 
(rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Tables.java  2007-01-25 07:03:17 UTC 
(rev 11613)
@@ -31,7 +31,7 @@
                fileTable = new FileTable(queueManager, indexBrowser, config);
                linkTable = new LinkTable(queueManager, indexBrowser);

-               searchBar = new SearchBar(queueManager, indexBrowser);
+               searchBar = new SearchBar(indexBrowser);

                split = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                                       linkTable.getPanel(),
@@ -56,6 +56,10 @@
                config.setValue("indexFileLinkSplit", 
Integer.toString(split.getDividerLocation()));
        }

+       public void stopRefresh() {
+               fileTable.stopRefresher();
+       }
+
        protected FileTable getFileTable() {
                return fileTable;
        }

Modified: trunk/apps/Thaw/src/thaw/plugins/index/UnknownIndexList.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/UnknownIndexList.java        
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/index/UnknownIndexList.java        
2007-01-25 07:03:17 UTC (rev 11613)
@@ -27,7 +27,7 @@

        private Link[] linkList;
        private boolean full;
-       private Vector vList; /* only when < 50 */
+       private Vector vList; /* only when < MAX_INDEXES */

        private JPanel panel;
        private JList list;
@@ -50,7 +50,7 @@
                offset = 0;
                full = false;
                vList = new Vector();
-               linkList = new Link[UnknownIndexList.MAX_INDEXES];
+               linkList = new Link[UnknownIndexList.MAX_INDEXES+1];

                for(int i = 0 ; i < linkList.length ; i++)
                        linkList[i] = null;
@@ -101,6 +101,13 @@
                return false;
        }

+       public void erase(int i) {
+               linkList[linkList.length-1] = null;
+               for (int j = i ; j < linkList.length-1; j++) {
+                       linkList[j] = linkList[j+1];
+               }
+       }
+
        public boolean removeLink(final Index index) {
                boolean ret = false;

@@ -108,14 +115,24 @@
                        if ((linkList[i] != null) && 
linkList[i].compare(index)) {
                                if (!full)
                                        vList.remove(linkList[i]);
-                               linkList[i] = null;
+                               erase(i);
                                ret = true;
                        }
                }

+               refresh();
+
                return ret;
        }

+       public void makePlace(int i) {
+               int j;
+               for (j = linkList.length - 1; j > i ; j--) {
+                       linkList[j] = linkList[j-1];
+               }
+               linkList[j] = null;
+       }
+
        /**
         * will check that the link link to an unknown index before adding
         */
@@ -123,7 +140,8 @@
                if ((link == null) || 
Index.isAlreadyKnown(indexBrowser.getDb(), link.getPublicKey()) || 
isInList(link))
                        return false;

-               linkList[linkList.length - 1 - offset] = link;
+               makePlace(0);
+               linkList[0] = link;

                if (!full) {
                        vList.add(0, link);
@@ -139,17 +157,22 @@
                        full = true;
                }

+               refresh();
+
                return true;
        }

        /**
         * will add the link from that index (if links link to unknown indexes)
         */
-       public boolean addLinks(final Index index) {
+       public boolean addLinks(final LinkList index) {
                boolean ret = false;

-               final Vector ll = index.getLinkList();
+               if (index == null)
+                       return false;

+               final Vector ll = index.getLinkList(null, false);
+
                if ((ll == null) || (ll.size() == 0))
                        return false;

@@ -198,16 +221,29 @@
        }

        public Vector getSelectedLinks() {
-               final Object[] sLink = list.getSelectedValues();
+               final Object[] sLink;
+
+               try {
+                       sLink = list.getSelectedValues();
+               } catch(ArrayIndexOutOfBoundsException e) {
+                       return null;
+               }
+
                final Vector vLink = new Vector();

-               for (int i = 0; i < sLink.length ; i++)
+               for (int i = 0; i < sLink.length ; i++) {
                        vLink.add(sLink[i]);
+               }

                return vLink;
        }


+       public void refresh() {
+               list.revalidate();
+               list.repaint();
+       }
+
        public void mouseClicked(final MouseEvent e) {
                Vector selection;

@@ -218,6 +254,9 @@

                selection = getSelectedLinks();

+               if (selection == null)
+                       return;
+
                if (e.getButton() == MouseEvent.BUTTON1) {
                        updateToolbar(selection);
                        toolbarModifier.displayButtonsInTheToolbar();

Modified: trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java 
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java 
2007-01-25 07:03:17 UTC (rev 11613)
@@ -748,6 +748,11 @@

        /** Guess a MIME type from a filename */
        public synchronized static String guessMIMEType(final String arg) {
+               if (arg == null) {
+                       Logger.error(new DefaultMIMETypes(), "Unable to guess 
mime type for file 'null' ");
+                       return null;
+               }
+
                final int x = arg.lastIndexOf('.');
                if((x == -1) || (x == arg.length()-1))
                        return DefaultMIMETypes.DEFAULT_MIME_TYPE;

Modified: trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java  
2007-01-25 03:40:46 UTC (rev 11612)
+++ trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java  
2007-01-25 07:03:17 UTC (rev 11613)
@@ -280,6 +280,10 @@
        public synchronized void update(final Observable o, final Object arg) {
                int i;

+               if (queries != null && (i = queries.indexOf(o)) >= 0) {
+                       this.notifyObservers(i);
+               }
+
                sortTable();

                if( (i = queries.indexOf(o)) >= 0) {


Reply via email to