Author: jflesch
Date: 2006-08-21 03:09:08 +0000 (Mon, 21 Aug 2006)
New Revision: 10221

Added:
   trunk/apps/Thaw/images/index.png
   trunk/apps/Thaw/src/thaw/gui/JDragTree.java
   trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java
   trunk/apps/Thaw/src/thaw/plugins/IndexEditor.java
   trunk/apps/Thaw/src/thaw/plugins/index/File.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileCategory.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileDetailsEditor.java
   trunk/apps/Thaw/src/thaw/plugins/index/FileList.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/IndexCategory.java
   trunk/apps/Thaw/src/thaw/plugins/index/IndexEditorPanel.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/SearchResult.java
Modified:
   trunk/apps/Thaw/src/thaw/core/Core.java
   trunk/apps/Thaw/src/thaw/core/IconBox.java
   trunk/apps/Thaw/src/thaw/core/Logger.java
   trunk/apps/Thaw/src/thaw/core/Main.java
   trunk/apps/Thaw/src/thaw/core/PluginManager.java
   trunk/apps/Thaw/src/thaw/core/QueueKeeper.java
   trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
   trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
   trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java
   trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
   trunk/apps/Thaw/src/thaw/i18n/thaw.properties
   trunk/apps/Thaw/src/thaw/plugins/fetchPlugin/KeyFileFilter.java
   trunk/apps/Thaw/src/thaw/plugins/index/TableCreator.java
   trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java
   trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueuePanel.java
   trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java
Log:
Basic file index management

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


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

Modified: trunk/apps/Thaw/src/thaw/core/Core.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Core.java     2006-08-20 22:58:19 UTC (rev 
10220)
+++ trunk/apps/Thaw/src/thaw/core/Core.java     2006-08-21 03:09:08 UTC (rev 
10221)
@@ -411,6 +411,8 @@
                        warningDialog.setModal(false);
                        warningDialog.setSize(500, 40);

+                       
warningDialog.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
+
                        JPanel warningPanel = new JPanel();

                        JLabel warningLabel = new 
JLabel(I18n.getMessage("thaw.warning.autoreconnecting"),

Modified: trunk/apps/Thaw/src/thaw/core/IconBox.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/IconBox.java  2006-08-20 22:58:19 UTC (rev 
10220)
+++ trunk/apps/Thaw/src/thaw/core/IconBox.java  2006-08-21 03:09:08 UTC (rev 
10221)
@@ -36,6 +36,8 @@

        public static ImageIcon insertAndAddToIndexAction;

+       public static ImageIcon minIndex;
+
        public static ImageIcon clearAction;

        public static ImageIcon settings;
@@ -87,6 +89,9 @@
                                new ImageIcon((new 
IconBox()).getClass().getClassLoader().getResource("min-go-next.png"));


+                       minIndex =
+                               new ImageIcon((new 
IconBox()).getClass().getClassLoader().getResource("index.png"));
+
                        downloads =
                                new ImageIcon((new 
IconBox()).getClass().getClassLoader().getResource("go-first.png"));
                        minDownloads =

Modified: trunk/apps/Thaw/src/thaw/core/Logger.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Logger.java   2006-08-20 22:58:19 UTC (rev 
10220)
+++ trunk/apps/Thaw/src/thaw/core/Logger.java   2006-08-21 03:09:08 UTC (rev 
10221)
@@ -20,7 +20,7 @@
         *
         * 2 or more is recommanded.
         */
-       public final static int LOG_LEVEL = 2;
+       public final static int LOG_LEVEL = 3;

        private static Vector logListeners = null;


Modified: trunk/apps/Thaw/src/thaw/core/Main.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Main.java     2006-08-20 22:58:19 UTC (rev 
10220)
+++ trunk/apps/Thaw/src/thaw/core/Main.java     2006-08-21 03:09:08 UTC (rev 
10221)
@@ -12,8 +12,8 @@
  */
 public class Main {

-       public final static String VERSION="0.5 WIP r at custom@";
-       //public final static String VERSION="0.5 Beta";
+       //public final static String VERSION="0.6 WIP r at custom@";
+       public final static String VERSION="0.5 Beta";

        /**
         * Look & feel use by GUI front end

Modified: trunk/apps/Thaw/src/thaw/core/PluginManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/PluginManager.java    2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/core/PluginManager.java    2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -11,7 +11,9 @@
        private final static String[] defaultPlugins = 
{"thaw.plugins.QueueWatcher",
                                                        
"thaw.plugins.InsertPlugin",
                                                        
"thaw.plugins.FetchPlugin",
-                                                       
"thaw.plugins.StatusBar"};
+                                                       
"thaw.plugins.StatusBar",
+                                                       
"thaw.plugins.IndexEditor",
+                                                       
"thaw.plugins.IndexBrowser"};

        private Core core = null;


Modified: trunk/apps/Thaw/src/thaw/core/QueueKeeper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/QueueKeeper.java      2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/core/QueueKeeper.java      2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -104,17 +104,17 @@
                try {
                        xmlBuilder = xmlFactory.newDocumentBuilder();
                } catch(javax.xml.parsers.ParserConfigurationException e) {
-                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e);
+                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e.toString());
                        return false;
                }

                try {
                        xmlDoc = xmlBuilder.parse(file);
                } catch(org.xml.sax.SAXException e) {
-                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e);
+                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e.toString());
                        return false;
                } catch(java.io.IOException e) {
-                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e);
+                       Logger.warning(new QueueKeeper(), "Unable to load queue 
because: "+e.toString());
                        return false;
                }

@@ -150,6 +150,9 @@


        private static Element saveQuery(FCPTransferQuery query, Document 
xmlDoc) {
+               if(!query.isPersistent())
+                       return null;
+
                if(query.isPersistent() && (query.isRunning() || 
query.isFinished()))
                        return null;


Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java      2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java      2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -129,17 +129,22 @@
                this.fileSize = 0;
                this.attempt = 0;

+               status = "Waiting";
+
                if(key.indexOf('/') == key.length()-1) {
                        filename = "index.html";
                } else {
-                       String cutcut[] = key.split("/");                       
-                       filename = cutcut[cutcut.length-1];
+                       String cutcut[] = key.split("/");
+
+                       if(!key.startsWith("USK@")) {
+                               filename = cutcut[cutcut.length-1];
+                       } else {
+                               filename = cutcut[cutcut.length-2];
+                       }
                }

                Logger.debug(this, "Query for getting "+key+" created");

-               status = "Waiting";
-
        }

        public boolean start(FCPQueueManager queueManager) {

Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java      2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java      2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -28,6 +28,7 @@
        private int priority = -1;
        private boolean global = true;
        private int persistence = 2;
+       private boolean getCHKOnly = false;

        private int progress = 0;
        private int toTheNodeProgress = 0;
@@ -59,7 +60,7 @@
        }

        /**
-        * To start a new insert.
+        * To start a new insertion.
         * @param keyType : 0 = CHK ; 1 = KSK ; 2 = SSK
         * @param rev  : ignored if key == CHK
         * @param name : ignored if key == CHK
@@ -70,6 +71,19 @@
                            int rev, String name,
                            String privateKey, int priority,
                            boolean global, int persistence) {
+               this(file, keyType, rev, name, privateKey, priority, global, 
persistence,
+                    false);
+       }
+
+       /**
+        * To start anew insertion.
+        */
+       public FCPClientPut(File file, int keyType,
+                           int rev, String name,
+                           String privateKey, int priority,
+                           boolean global, int persistence,
+                           boolean getCHKOnly) {
+               this.getCHKOnly = getCHKOnly;
                this.localFile = file;
                this.name = file.getName();
                fileSize = file.length();
@@ -338,16 +352,23 @@
                }

                msg.setValue("Identifier", identifier);
-               msg.setValue("Verbosity", "512");
                msg.setValue("MaxRetries", "-1");
                msg.setValue("PriorityClass", Integer.toString(priority));
-               msg.setValue("GetCHKOnly", "false");
+
+               if(getCHKOnly) {
+                       msg.setValue("GetCHKOnly", "true");
+                       msg.setValue("Verbosity", "0");
+               } else {
+                       msg.setValue("GetCHKOnly", "false");
+                       msg.setValue("Verbosity", "512");
+               }
+
                if(global)
                        msg.setValue("Global", "true");
                else
                        msg.setValue("Global", "false");
                msg.setValue("ClientToken", localFile.getPath());
-               
+
                switch(persistence) {
                case(0): msg.setValue("Persistence", "forever"); break;
                case(1): msg.setValue("Persistence", "reboot"); break;
@@ -472,7 +493,7 @@
        public boolean stop(FCPQueueManager queueManager) {
                if(removeRequest()) {
                        status = "Stopped";
-                       finished = false;
+                       finished = true;
                        successful = false;
                        fatal= true;
                        running = false;
@@ -511,12 +532,33 @@
                                finished = false;
                                successful = false;

-                               status = "Inserting";
-
-                               publicKey = msg.getValue("URI");
+                               if(keyType == 0)
+                                       publicKey = msg.getValue("URI") + "/" + 
getFilename();
+                               else
+                                       publicKey = msg.getValue("URI");
                                publicKey = publicKey.replaceAll("freenet:", 
"");

+                               Logger.info(this, "URIGenerated: "+publicKey);

+                               if(getCHKOnly) {
+                                       status = "CHK";
+
+                                       progress = 100;
+                                       toTheNodeProgress = 100;
+                                       running = false;
+                                       finished = true;
+                                       successful = true;
+                                       fatal = false;
+                                       sending = false;
+
+                                       setChanged();
+                                       notifyObservers();
+                                       
queueManager.getQueryManager().deleteObserver(this);
+                                       return;
+                               }
+                               
+                               status = "Inserting";
+                               
                                if(keyType == 0)
                                        publicKey = publicKey + "/" +name;

@@ -543,8 +585,10 @@
                                        publicKey = publicKey + "/" + name;
                                if(keyType == 1)
                                        publicKey = "KSK@"+name+"-" + 
Integer.toString(rev);
+                               //if(keyType == 2)
+                               //      publicKey = publicKey + "/" + name + 
"-" + Integer.toString(rev);
                                if(keyType == 2)
-                                       publicKey = publicKey + "/" + name + 
"-" + Integer.toString(rev);
+                                       publicKey = publicKey;


                                status = "Finished";
@@ -904,7 +948,7 @@
                        privateKey = null;

                publicKey = (String)parameters.get("publicKey");
-               if(privateKey == null || publicKey.equals(""))
+               if(privateKey == null || publicKey == null || 
publicKey.equals(""))
                        publicKey = null;

                priority = Integer.parseInt((String)parameters.get("priority"));

Modified: trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java        2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPMessage.java        2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -45,6 +45,7 @@


                setMessageName(lines[i]);
+               Logger.info(this, "Message (Node >> Thaw): "+lines[i]);


                for(i++; i < lines.length ; i++) {
@@ -56,7 +57,7 @@
                        String[] affectation = lines[i].split("=");

                        if(affectation.length < 2) {
-                               Logger.notice(this, "Malformed message");
+                               Logger.warning(this, "Malformed message");
                                continue;
                        }

@@ -84,8 +85,6 @@
                        Logger.notice(this, "Name shouldn't contain '\n'");
                }

-               Logger.notice(this, "Message: "+name);
-
                messageName = name;
        }

@@ -133,6 +132,8 @@
        public String toString() {
                String result = "";

+               Logger.info(this, "Message (Node << Thaw): "+getMessageName());
+
                result = result + getMessageName() + "\n";

                for(Enumeration fieldNames = fields.keys() ; 
fieldNames.hasMoreElements();) {

Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java   2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java   2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -227,6 +227,9 @@

        private boolean isTheSame(FCPTransferQuery queryA,
                                  FCPTransferQuery queryB) {
+               if(queryA.getQueryType() != queryB.getQueryType())
+                       return false;
+
                if(queryA.getIdentifier() != null && queryB.getIdentifier() != 
null) {
                        
if(queryA.getIdentifier().equals(queryB.getIdentifier())) {
                                Logger.debug(this, "isTheSame(): Identifier");

Added: trunk/apps/Thaw/src/thaw/gui/JDragTree.java
===================================================================
--- trunk/apps/Thaw/src/thaw/gui/JDragTree.java 2006-08-20 22:58:19 UTC (rev 
10220)
+++ trunk/apps/Thaw/src/thaw/gui/JDragTree.java 2006-08-21 03:09:08 UTC (rev 
10221)
@@ -0,0 +1,499 @@
+/*
+ JDragTree.java / Frost
+ Copyright (C) 2003  Frost Project <jtcfrost.sourceforge.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+package thaw.gui;
+
+import java.awt.*;
+import java.awt.datatransfer.*;
+import java.awt.dnd.*;
+import java.awt.event.*;
+import java.awt.geom.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.logging.*;
+
+import javax.swing.*;
+import javax.swing.tree.*;
+
+public class JDragTree extends JTree implements DragGestureListener, 
DragSourceListener {
+
+        //     DropTargetListener interface object...
+        private class CDropTargetListener implements DropTargetListener 
+        {      
+               
+                // Fields...
+                private TreePath        _pathLast       = null;
+                private Rectangle2D     _raCueLine      = new 
Rectangle2D.Float();
+                private Rectangle2D     _raGhost        = new 
Rectangle2D.Float();
+                private Color           _colorCueLine;
+                private Point           _ptLast         = new Point();
+                private javax.swing.Timer           _timerHover;
+                private int             _nLeftRight     = 0;    // Cumulative 
left/right mouse movement
+                private int             _nShift         = 0;
+
+                // Constructor...
+                public CDropTargetListener()
+                {
+                        _colorCueLine = new Color(
+                                        SystemColor.controlShadow.getRed(),
+                                        SystemColor.controlShadow.getGreen(),
+                                        SystemColor.controlShadow.getBlue(),
+                                        64
+                                  );
+
+                        // Set up a hover timer, so that a node will be 
automatically expanded or collapsed
+                        // if the user lingers on it for more than a short time
+                        _timerHover = new javax.swing.Timer(1000, new 
ActionListener()
+                        {
+                                public void actionPerformed(ActionEvent e)
+                                {
+                                        _nLeftRight = 0;    // Reset 
left/right movement trend
+                                        if (isRootPath(_pathLast))
+                                                return; // Do nothing if we 
are hovering over the root node
+                                        if (isExpanded(_pathLast))
+                                                collapsePath(_pathLast);
+                                        else
+                                                expandPath(_pathLast);
+                                }
+                        });
+                        _timerHover.setRepeats(false);  // Set timer to 
one-shot mode
+                }
+
+                // DropTargetListener interface
+                public void dragEnter(DropTargetDragEvent e)
+                {
+                        if (!isDragAcceptable(e))
+                                e.rejectDrag();
+                        else
+                                e.acceptDrag(e.getDropAction());
+                }
+
+                public void dragExit(DropTargetEvent e)
+                {
+                        if (!DragSource.isDragImageSupported())
+                        {
+                                repaint(_raGhost.getBounds());
+                        }
+                }
+
+                /**
+                * This is where the ghost image is drawn
+                */
+                public void dragOver(DropTargetDragEvent e)
+                {
+             if( e==null || _raGhost == null || _ptLast == null || 
+                 _ptOffset == null || _imgGhost == null || _raCueLine == null 
) {
+                 return;
+             }
+                        // Even if the mouse is not moving, this method is 
still invoked 10 times per second
+                        Point pt = e.getLocation();
+             if(pt==null) {
+                 return;
+             }
+                        if (pt.equals(_ptLast))
+                                return;
+
+                        // Try to determine whether the user is flicking the 
cursor right or left
+                        int nDeltaLeftRight = pt.x - _ptLast.x;
+                        if ( (_nLeftRight > 0 && nDeltaLeftRight < 0) || 
(_nLeftRight < 0 && nDeltaLeftRight > 0) )
+                                _nLeftRight = 0;
+                        _nLeftRight += nDeltaLeftRight;
+                        _ptLast = pt;
+                        Graphics2D g2 = (Graphics2D) getGraphics();
+             if( g2 == null ) {
+                 return;
+             }
+             
+                        // If a drag image is not supported by the platform, 
then draw my own drag image
+                        if (!DragSource.isDragImageSupported())
+                        {
+                                paintImmediately(_raGhost.getBounds()); // Rub 
out the last ghost image and cue line
+                                // And remember where we are about to draw the 
new ghost image
+                                _raGhost.setRect(pt.x - _ptOffset.x, pt.y - 
_ptOffset.y, _imgGhost.getWidth(), _imgGhost.getHeight());
+                                g2.drawImage(_imgGhost, 
AffineTransform.getTranslateInstance(_raGhost.getX(), _raGhost.getY()), null);
+                        }
+                        else    // Just rub out the last cue line
+                                paintImmediately(_raCueLine.getBounds());
+
+                        TreePath path = getClosestPathForLocation(pt.x, pt.y);
+                        if (!(path == _pathLast))
+                        {
+                                _nLeftRight = 0;    // We've moved up or down, 
so reset left/right movement trend
+                                _pathLast = path;
+                                _timerHover.restart();
+                        }
+
+                        // In any case draw (over the ghost image if 
necessary) a cue line indicating where a drop will occur
+                        Rectangle raPath = getPathBounds(path);
+                        _raCueLine.setRect(0,  
raPath.y+(int)raPath.getHeight(), getWidth(), 2);
+
+                        g2.setColor(_colorCueLine);
+                        g2.fill(_raCueLine);
+
+                        _nShift = 0;
+
+                        // And include the cue line in the area to be rubbed 
out next time
+                        _raGhost = _raGhost.createUnion(_raCueLine);
+
+                        // Do this if you want to prohibit dropping onto the 
drag source
+                        if (path.equals(_pathSource))
+                                e.rejectDrag();
+                        else
+                                e.acceptDrag(e.getDropAction());
+                }
+
+                public void dropActionChanged(DropTargetDragEvent e)
+                {
+                        if (!isDragAcceptable(e))
+                                e.rejectDrag();
+                        else
+                                e.acceptDrag(e.getDropAction());
+                }
+
+                public void drop(DropTargetDropEvent e)
+                {
+                        _timerHover.stop(); // Prevent hover timer from doing 
an unwanted expandPath or collapsePath
+
+                        if (!isDropAcceptable(e))
+                        {
+                                e.rejectDrop();
+                                return;
+                        }
+
+                        e.acceptDrop(e.getDropAction());
+
+                        Transferable transferable = e.getTransferable();
+
+                        DataFlavor[] flavors = 
transferable.getTransferDataFlavors();
+
+                        for (int i = 0; i < flavors.length; i++ )
+                        {
+                                DataFlavor flavor = flavors[i];
+                                if 
(flavor.isMimeTypeEqual(DataFlavor.javaJVMLocalObjectMimeType))
+                                {
+                                        try
+                                        {
+                                                Point pt = e.getLocation();
+                                                TreePath pathTarget = 
getClosestPathForLocation(pt.x, pt.y);
+                                                TreePath pathSource = 
(TreePath) transferable.getTransferData(flavor);
+
+                                                if( pathTarget == null || 
pathSource == null )
+                                                {
+                                                        e.dropComplete(false);
+                                                        return;
+                                                }
+
+                                                DefaultMutableTreeNode 
sourceNode = (DefaultMutableTreeNode)pathSource.getLastPathComponent();
+                                                DefaultMutableTreeNode 
oldParent = (DefaultMutableTreeNode)sourceNode.getParent();
+
+                                                DefaultMutableTreeNode 
targetNode = (DefaultMutableTreeNode)pathTarget.getLastPathComponent();
+                                                DefaultMutableTreeNode 
newParent = (DefaultMutableTreeNode)targetNode.getParent();
+
+                                                if( !sourceNode.isLeaf() && 
targetNode.getParent() == sourceNode )
+                                                {
+                                                        // trying to drag a 
folder into its own childs
+                                                        e.dropComplete(false);
+                                                        return;
+                                                }
+
+                                                DefaultTreeModel model = 
(DefaultTreeModel)getModel();
+                                                TreePath pathNewChild = null;
+
+                                                if( targetNode.isLeaf() || 
isCollapsed(pathTarget) )
+                                                {
+                                                        // collapsed tree node 
or leaf
+                                                        // dropped on a leaf, 
insert into leaf's parent AFTER leaf
+                                                        int idx = 
newParent.getIndex(targetNode);
+                                                        if( idx < 0 )
+                                                        {
+                                                                
logger.warning("child not found in parent!!!");
+                                                                
e.dropComplete(false);
+                                                                return;
+                                                        }
+                                                        else
+                                                        {
+                                                                idx++; // 
insert AFTER targetNode
+
+                                                                // remove node 
from oldParent ...
+                                                                Object[] 
removedChilds = { sourceNode };
+                                                                int[] 
childIndices = { oldParent.getIndex(sourceNode) };
+                                                                
sourceNode.removeFromParent();
+                                                                
model.nodesWereRemoved( oldParent, childIndices, removedChilds );
+
+                                                                // ... and 
insert into newParent
+                                                                if( idx >= 
newParent.getChildCount() )
+                                                                {
+                                                                        
newParent.add( sourceNode );
+                                                                        int 
insertedIndex[] = { newParent.getChildCount()-1 };
+                                                                        
model.nodesWereInserted( newParent, insertedIndex );
+                                                                }
+                                                                else
+                                                                {
+                                                                        
newParent.insert(sourceNode, idx);
+                                                                        int 
insertedIndex[] = { idx };
+                                                                        
model.nodesWereInserted( newParent, insertedIndex );
+                                                                }
+                                                        }
+                                                }
+                                                else
+                                                {
+                                                        // expanded node, 
insert UNDER the node (before first child)
+                                                        // remove node from 
oldParent ...
+                                                        Object[] removedChilds 
= { sourceNode };
+                                                        int[] childIndices = { 
oldParent.getIndex(sourceNode) };
+                                                        
sourceNode.removeFromParent();
+                                                        
model.nodesWereRemoved( oldParent, childIndices, removedChilds );
+                                                        // ... and add to 
newParent
+                                                        targetNode.insert( 
sourceNode, 0 );
+                                                        int insertedIndex[] = 
{ 0 };
+                                                        
model.nodesWereInserted( targetNode, insertedIndex );
+                                                }
+
+                                                if (pathNewChild != null)
+                                                        
setSelectionPath(pathNewChild); // Mark this as the selected path in the tree
+                                                break; // No need to check 
remaining flavors
+                                        }
+                                        catch (UnsupportedFlavorException ufe)
+                                        {
+                                                logger.log(Level.SEVERE, 
"Exception thrown in drop(DropTargetDropEvent e)", ufe);
+                                                e.dropComplete(false);
+                                                return;
+                                        }
+                                        catch (IOException ioe)
+                                        {
+                                                logger.log(Level.SEVERE, 
"Exception thrown in drop(DropTargetDropEvent e)", ioe);
+                                                e.dropComplete(false);
+                                                return;
+                                        }
+                                }
+                        }
+                        e.dropComplete(true);
+                }
+
+                // Helpers...
+                public boolean isDragAcceptable(DropTargetDragEvent e)
+                {
+                        // Only accept COPY or MOVE gestures (ie LINK is not 
supported)
+                        if ((e.getDropAction() & DnDConstants.ACTION_MOVE) == 
0)
+                                return false;
+
+                        // Only accept this particular flavor
+                        if (!e.isDataFlavorSupported(TREEPATH_FLAVOR))
+                                return false;
+
+                        // Do this if you want to prohibit dropping onto the 
drag source...
+                        Point pt = e.getLocation();
+                        TreePath path = getClosestPathForLocation(pt.x, pt.y);
+                        if(path == null || path.equals(_pathSource))
+                                return false;
+
+                        return true;
+                }
+
+                public boolean isDropAcceptable(DropTargetDropEvent e)
+                {
+                        // Only accept COPY or MOVE gestures (ie LINK is not 
supported)
+                        if ((e.getDropAction() & DnDConstants.ACTION_MOVE) == 
0)
+                                return false;
+
+                        // Only accept this particular flavor
+                        if (!e.isDataFlavorSupported(TREEPATH_FLAVOR))
+                                return false;
+
+                        // Do this if you want to prohibit dropping onto the 
drag source...
+                        Point pt = e.getLocation();
+                        TreePath path = getClosestPathForLocation(pt.x, pt.y);
+                        if( path == null || path.equals(_pathSource))
+                                return false;
+
+                        return true;
+                }
+       }
+        
+       /**
+       * This represents a TreePath (a node in a JTree) that can be 
transferred between a drag source and a drop target.
+       */
+       private class CTransferableTreePath implements Transferable
+       {
+               private TreePath        _path;
+               /**
+               * Constructs a transferrable tree path object for the specified 
path.
+               */
+               public CTransferableTreePath(TreePath path)
+               {
+                       _path = path;
+               }
+
+               // Transferable interface methods...
+               public DataFlavor[] getTransferDataFlavors()
+               {
+                       return _flavors;
+               }
+
+               public boolean isDataFlavorSupported(DataFlavor flavor)
+               {
+                       return 
java.util.Arrays.asList(_flavors).contains(flavor);
+               }
+
+               public synchronized Object getTransferData(DataFlavor flavor) 
throws UnsupportedFlavorException
+               {
+                       if 
(flavor.isMimeTypeEqual(TREEPATH_FLAVOR.getMimeType()))
+                               return _path;
+                       else
+                               throw new UnsupportedFlavorException(flavor);
+               }
+       } 
+
+       private static Logger logger = 
Logger.getLogger(JDragTree.class.getName());
+       
+       private TreePath        _pathSource;                // The path being 
dragged
+       private BufferedImage   _imgGhost;                  // The 'drag image'
+       private Point           _ptOffset = new Point();    // Where, in the 
drag image, the mouse was clicked
+
+       // The type of DnD object being dragged...
+       public final static DataFlavor TREEPATH_FLAVOR = new 
DataFlavor(DataFlavor.javaJVMLocalObjectMimeType, "TreePath");
+       private DataFlavor[]    _flavors = { TREEPATH_FLAVOR };
+       
+       private DragSource dragSource = null;
+       private DragGestureRecognizer dgRecognizer = null;
+       private DropTarget dropTarget = null;
+
+       /**
+        * @param root
+        */
+       public JDragTree(TreeNode root) {
+               super(root);
+               initialize();
+       }
+       
+       /**
+        * @param root
+        */
+       public JDragTree(TreeModel model) {
+               super(model);
+               initialize();
+       }
+       
+       /**
+        * 
+        */
+       private void initialize() {
+               // install drag n drop support
+               dragSource = DragSource.getDefaultDragSource();
+               dgRecognizer = 
dragSource.createDefaultDragGestureRecognizer(this,
+                                                                               
                                                         
DnDConstants.ACTION_MOVE,
+                                                                               
                                                         this);
+               // don't act on right mouse button
+               dgRecognizer.setSourceActions(dgRecognizer.getSourceActions() & 
~InputEvent.BUTTON3_MASK & ~InputEvent.BUTTON2_MASK);
+               dropTarget = new DropTarget(this, new CDropTargetListener());
+       }
+       
+       /**
+        * @param path
+        * @return
+        */
+       private boolean isRootPath(TreePath path)
+       {
+               return isRootVisible() && getRowForPath(path) == 0;
+       }
+
+       // DragSourceListener interface methods
+       public void dragDropEnd(DragSourceDropEvent e)
+       {
+               this.repaint();
+       }
+
+       public void dragEnter(DragSourceDragEvent e) {}
+
+       public void dragExit(DragSourceEvent e) {}
+
+       // DragGestureListener interface method
+       public void dragGestureRecognized(DragGestureEvent e)
+       {
+               //we should make sure we aren't in edit mode
+               InputEvent ievent=e.getTriggerEvent();
+               if( ievent instanceof MouseEvent )
+               {
+                       //even though I tell dgRecognizer to ignore the the 
right mouse button,
+                       // it thinks the RMB starts a drag event...argh
+                       if( (((MouseEvent)ievent).getModifiers() & 
InputEvent.BUTTON3_MASK) != 0 )
+                       {
+                               return;
+                       }
+               }
+
+               // begin dnd
+               Point ptDragOrigin = e.getDragOrigin();
+               TreePath path = getPathForLocation(ptDragOrigin.x, 
ptDragOrigin.y);
+               if (path == null)
+                       return;
+               if (isRootPath(path))
+                       return; // Ignore user trying to drag the root node
+
+               // Work out the offset of the drag point from the TreePath 
bounding rectangle origin
+               Rectangle raPath = getPathBounds(path);
+               _ptOffset.setLocation(ptDragOrigin.x-raPath.x, 
ptDragOrigin.y-raPath.y);
+
+               // Get the cell renderer (which is a JLabel) for the path being 
dragged
+               JLabel lbl = (JLabel) 
getCellRenderer().getTreeCellRendererComponent
+                                                               (
+                                                                       this,   
                                        // tree
+                                                                       
path.getLastPathComponent(),                    // value
+                                                                       false,  
                                        // isSelected   (dont want a colored 
background)
+                                                                       
isExpanded(path),                               // isExpanded
+                                                                       
getModel().isLeaf(path.getLastPathComponent()), // isLeaf
+                                                                       0,      
                                        // row          (not important for 
rendering)
+                                                                       false   
                                        // hasFocus     (dont want a focus 
rectangle)
+                                                               );
+               lbl.setSize((int)raPath.getWidth(), (int)raPath.getHeight()); 
// <-- The layout manager would normally do this
+
+               // Get a buffered image of the selection for dragging a ghost 
image
+               _imgGhost = new BufferedImage((int)raPath.getWidth(), 
(int)raPath.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
+               Graphics2D g2 = _imgGhost.createGraphics();
+
+               // Ask the cell renderer to paint itself into the BufferedImage
+               g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 
0.5f));      // Make the image ghostlike
+               lbl.paint(g2);
+
+               // Now paint a gradient UNDER the ghosted JLabel text (but not 
under the icon if any)
+               // Note: this will need tweaking if your icon is not positioned 
to the left of the text
+               Icon icon = lbl.getIcon();
+               int nStartOfText = (icon == null) ? 0 : 
icon.getIconWidth()+lbl.getIconTextGap();
+               
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 0.5f)); // 
Make the gradient ghostlike
+               g2.setPaint(new GradientPaint(nStartOfText, 0, 
SystemColor.controlShadow,
+                                                                         
getWidth(),   0, new Color(255,255,255,0)));
+               g2.fillRect(nStartOfText, 0, getWidth(), _imgGhost.getHeight());
+               g2.dispose();
+
+               setSelectionPath(path); // Select this path in the tree
+
+               // Wrap the path being transferred into a Transferable object
+               Transferable transferable = new CTransferableTreePath(path);
+
+               // Remember the path being dragged (because if it is being 
moved, we will have to delete it later)
+               _pathSource = path;
+
+               // We pass our drag image just in case it IS supported by the 
platform
+               e.startDrag(null, _imgGhost, new Point(5,5), transferable, 
this);
+       }
+
+       public void dragOver(DragSourceDragEvent e) {}
+
+       public void dropActionChanged(DragSourceDragEvent e) {}
+
+}

Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -15,6 +15,12 @@
 thaw.common.insertions=Insertions
 thaw.common.downloads=Downloads

+thaw.common.uploading=Uploading
+
+thaw.common.downloading=Downloading
+thaw.common.inserting=Inserting
+
+thaw.common.action.download=Download
 thaw.common.fetch=Fetch

 thaw.common.file=File
@@ -55,6 +61,8 @@
 thaw.common.unknown=Unknown
 thaw.common.estimation=estimation
 thaw.common.failed=FAILED
+thaw.common.done=Done
+thaw.common.ok=Ok

 ## Errors
 thaw.error.idAlreadyUsed=Unable to connect. Our Id is already used by another 
client connected to the node.
@@ -177,15 +185,25 @@

 # In internal, thaw use the word "category" instead of "folders"

+thaw.plugin.index.category=Category
+
 thaw.plugin.index.editor=Your shared files
+thaw.plugin.index.browser=Index browser
+
+thaw.plugin.index.yourIndexes=Your indexes
+thaw.plugin.index.indexes=Indexes
+
 thaw.plugin.index.addIndex=Add a file index
 thaw.plugin.index.createIndex=Create a file index
 thaw.plugin.index.addCategory=Add a folder
 thaw.plugin.index.rename=Rename
 thaw.plugin.index.delete=Delete
 thaw.plugin.index.insertIndex=Insert / update this index
+thaw.plugin.index.insertIndexes=Insert / update these indexes
 thaw.plugin.index.downloadIndex=Download / update this index
+thaw.plugin.index.downloadIndexes=Download / update these indexes
 thaw.plugin.index.copyKey=Copy index key(s) to clipboard
+thaw.plugin.index.recalculateKeys=Recalculate keys

 thaw.plugin.index.categoryName=Folder Name ?
 thaw.plugin.index.indexName=Index name ?
@@ -201,3 +219,5 @@
 thaw.plugin.index.addFilesWithInserting=Insert file(s) on Freenet and add them 
to this index
 thaw.plugin.index.addFilesWithoutInserting=Add file(s) to this index
 thaw.plugin.index.addLink=Add a link to another index
+
+thaw.plugin.index.insert=Insert

Added: trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java  2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/IndexBrowser.java  2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -0,0 +1,60 @@
+package thaw.plugins;
+
+import thaw.core.*;
+
+import thaw.plugins.index.*;
+
+public class IndexBrowser implements Plugin {
+       private Core core;
+       private Hsqldb hsqldb;
+
+       private IndexBrowserPanel browserPanel;
+
+       public IndexBrowser() {
+
+       }
+
+       public boolean run(Core core) {
+               this.core = core;
+
+               if(core.getPluginManager().getPlugin("thaw.plugins.Hsqldb") == 
null) {
+                       Logger.info(this, "Loading Hsqldb plugin");
+
+                       
if(!core.getPluginManager().loadPlugin("thaw.plugins.Hsqldb")
+                          || 
!core.getPluginManager().runPlugin("thaw.plugins.Hsqldb")) {
+                               Logger.error(this, "Unable to load 
thaw.plugins.Hsqldb !");
+                               return false;
+                       }
+               }
+
+               hsqldb = 
(Hsqldb)core.getPluginManager().getPlugin("thaw.plugins.Hsqldb");
+
+               hsqldb.registerChild(this);
+
+               TableCreator.createTables(hsqldb);
+
+               browserPanel = new IndexBrowserPanel(hsqldb, 
core.getQueueManager());
+
+               
core.getMainWindow().addTab(I18n.getMessage("thaw.plugin.index.browser"),
+                                           IconBox.minIndexBrowser,
+                                           browserPanel.getPanel());
+
+               return true;
+       }
+
+       public boolean stop() {
+               core.getMainWindow().removeTab(browserPanel.getPanel());
+
+               browserPanel.save();
+
+               hsqldb.unregisterChild(this);
+
+               return true;
+       }
+
+       public String getNameForUser() {
+               return I18n.getMessage("thaw.plugin.index.browser");
+       }
+
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/IndexEditor.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/IndexEditor.java   2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/IndexEditor.java   2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -0,0 +1,66 @@
+package thaw.plugins;
+
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+
+import thaw.core.*;
+import thaw.fcp.*;
+
+import thaw.plugins.index.*;
+
+public class IndexEditor implements Plugin {
+       private Core core;
+       private Hsqldb hsqldb;
+
+       private IndexEditorPanel editorPanel;
+
+       public IndexEditor() {
+
+       }
+
+       public boolean run(Core core) {
+               this.core = core;
+
+               if(core.getPluginManager().getPlugin("thaw.plugins.Hsqldb") == 
null) {
+                       Logger.info(this, "Loading Hsqldb plugin");
+
+                       
if(!core.getPluginManager().loadPlugin("thaw.plugins.Hsqldb")
+                          || 
!core.getPluginManager().runPlugin("thaw.plugins.Hsqldb")) {
+                               Logger.error(this, "Unable to load 
thaw.plugins.Hsqldb !");
+                               return false;
+                       }
+               }
+
+               hsqldb = 
(Hsqldb)core.getPluginManager().getPlugin("thaw.plugins.Hsqldb");
+
+               hsqldb.registerChild(this);
+
+               TableCreator.createTables(hsqldb);
+
+               
+               editorPanel = new IndexEditorPanel(hsqldb, 
core.getQueueManager());
+
+
+               
core.getMainWindow().addTab(I18n.getMessage("thaw.plugin.index.editor"),
+                                           IconBox.minIndexEditor,
+                                           editorPanel.getPanel());
+                                           
+
+               return true;
+       }
+
+
+       public boolean stop() {
+               core.getMainWindow().removeTab(editorPanel.getPanel());
+
+               editorPanel.save();
+
+               hsqldb.unregisterChild(this);
+
+               return true;
+       }
+
+       public String getNameForUser() {
+               return I18n.getMessage("thaw.plugin.index.editor");
+       }
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/fetchPlugin/KeyFileFilter.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/fetchPlugin/KeyFileFilter.java     
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/fetchPlugin/KeyFileFilter.java     
2006-08-21 03:09:08 UTC (rev 10221)
@@ -44,7 +44,7 @@
                        String line = null;

                        while((line = in.readLine()) != null) {
-                               String[] pieces = 
line.split("[^-\\?.a-zA-Z0-9,~%@/'_]");
+                               String[] pieces = line.split("[^- 
\\?.a-zA-Z0-9,~%@/'_]");

                                for(int i = 0 ; i < pieces.length ; i++) {
                                        if(pieces[i].matches(".{3}@.*,.*"))

Added: trunk/apps/Thaw/src/thaw/plugins/index/File.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/File.java    2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/File.java    2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -0,0 +1,331 @@
+package thaw.plugins.index;
+
+import java.sql.*;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+import thaw.core.Logger;
+import thaw.fcp.*;
+import thaw.plugins.Hsqldb;
+
+import thaw.plugins.insertPlugin.DefaultMIMETypes;
+
+public class File extends java.util.Observable implements java.util.Observer {
+       private int id = -1; /* -1 = undefined */
+
+       private String fileName = null;
+       private String publicKey = null;
+       private String mime = null;
+       private long size = -1;
+       private String category = null;
+
+       private String localPath = null;
+       private FCPTransferQuery transfer = null; /* can be null */
+
+       private Index parent;
+
+       private Hsqldb db;
+
+       /**
+        * @param path Local path
+        * @param transfer Corresponding tranfer (can be null).
+        */
+       public File(Hsqldb db, String path, String category, Index parent, 
FCPTransferQuery transfer) {
+               this.db = db;
+
+               id = -1;
+               localPath = path;
+               this.transfer = transfer;
+
+               String[] pathElements = 
localPath.split(java.io.File.separator.replaceAll("\\\\", "\\\\\\\\"));
+               fileName = pathElements[pathElements.length-1];
+
+               size = (new java.io.File(path)).length();
+
+               this.category = category;
+               this.parent = parent;
+
+               if(transfer != null)
+                       ((java.util.Observable)transfer).addObserver(this);
+       }
+
+
+       public File(Hsqldb db, ResultSet resultSet, Index parent) throws 
SQLException {
+               this.db = db;
+
+               id = resultSet.getInt("id");
+               publicKey = resultSet.getString("publicKey");
+               localPath = resultSet.getString("localPath");
+               size = resultSet.getLong("size");
+               category = resultSet.getString("category");
+
+               deduceFilenameFromKey();
+               
+               parent = parent;
+       }
+
+       public File(Hsqldb db, Element fileElement, Index parent) {
+               this.db = db;
+
+               id = Integer.parseInt(fileElement.getAttribute("id"));
+               publicKey = fileElement.getAttribute("key");
+               
+               localPath = null;
+               
+               size = Long.parseLong(fileElement.getAttribute("size"));
+               
+               setOptions(fileElement.getChildNodes());
+
+               deduceFilenameFromKey();
+
+               this.parent = parent;
+       }
+       
+       public void deduceFilenameFromKey() {
+               if(publicKey.indexOf("/") < 0) {
+                       fileName = publicKey;
+                       publicKey = null;
+                       return;
+               }
+
+               String[] keyParts = publicKey.split("/");
+               fileName = keyParts[keyParts.length-1];
+       }
+
+       public void setOptions(NodeList list) {
+               for(int i = 0 ; i < list.getLength() ; i++) {
+                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
+                               Element option = (Element)list.item(i);
+
+                               
if(option.getAttribute("name").equals("category"))
+                                       category = option.getAttribute("value");
+                               else {
+                                       /* TODO */
+                               }
+                       }
+               }
+       }
+
+       public void setParent(Index parent) {
+               this.parent = parent;
+       }
+
+       public Index getParent() {
+               return parent;
+       }
+
+       public String getFilename() {
+               return fileName;
+       }
+
+       public long getSize() {
+               return size;
+       }
+
+       public String getLocalPath() {
+               return localPath;
+       }
+
+       public String getCategory() {
+               return category;
+       }
+
+       public String getPublicKey() {
+               return publicKey;
+       }
+
+       public void setPublicKey(String publicKey) {
+               this.publicKey = publicKey;
+
+               setChanged();
+               notifyObservers();
+       }
+
+       public FCPTransferQuery getTransfer() {
+               return transfer;
+       }
+
+       public void setTransfer(FCPTransferQuery query) {
+               transfer = query;
+
+               if(transfer instanceof FCPClientPut)
+                       ((FCPClientPut)transfer).addObserver(this);
+
+               setChanged();
+               notifyObservers(query);
+       }
+
+       public void insert() {
+               try {
+                       PreparedStatement st;
+
+                       st = db.getConnection().prepareStatement("SELECT id 
FROM files ORDER BY id DESC LIMIT 1");
+
+                       try {
+                               if(st.execute()) {
+                                       ResultSet result = st.getResultSet();
+                                       result.next();
+                                       id = result.getInt("id")+1;
+                               } else
+                                       id = 1;
+                       } catch(SQLException e) {
+                               id = 1;
+                       }
+                       
+
+                       st = db.getConnection().prepareStatement("INSERT INTO 
files (id, publicKey, "+
+                                                                      
"localPath, mime, size, category, indexParent) "+
+                                                                      "VALUES 
(?, ?, ?, ?, ?, ?, ?)");
+                       st.setInt(1, id);
+
+                       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);
+
+                       if(mime != null)
+                               st.setString(4, mime);
+                       else
+                               st.setNull(4, Types.VARCHAR);
+
+                       st.setLong(5, size);
+                       
+                       if(category != null)
+                               st.setString(6, category);
+                       else
+                               st.setNull(6, Types.VARCHAR);
+
+                       Logger.info(this, "PARENT : "+parent.getId());
+
+                       st.setInt(7, parent.getId());
+
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to insert file 
'"+fileName+"' because: "+e.toString());
+               }
+               
+       }
+
+       public void delete() {
+               try {
+                       PreparedStatement st;
+
+                       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 
'"+fileName+"' because: "+e.toString());
+               }       
+       }
+
+       public void update() {
+               try {
+                       PreparedStatement st;
+
+                       st = db.getConnection().prepareStatement("UPDATE files 
SET publicKey = ?, localPath = ?, mime= ?, size = ?, category = ?, indexParent 
= ? WHERE id = ?");
+
+                       if(publicKey != null)
+                               st.setString(1, publicKey);
+                       else
+                               st.setString(1, fileName);
+
+                       if(localPath != null)
+                               st.setString(2, localPath);
+                       else
+                               st.setNull(2, Types.VARCHAR);
+
+                       if(mime != null)
+                               st.setString(3, mime);
+                       else
+                               st.setNull(3, Types.VARCHAR);
+
+                       st.setLong(4, size);
+                       
+                       if(category != null)
+                               st.setString(5, category);
+                       else
+                               st.setNull(5, Types.VARCHAR);
+
+                       st.setInt(6, getParent().getId());
+
+                       st.setInt(7, id);
+
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to update file 
'"+fileName+"' because: "+e.toString());
+               }
+       }
+
+       
+       public void update(java.util.Observable o, Object param) {
+               if(o == transfer) {
+                       if(transfer.isFinished() && transfer instanceof 
FCPClientPut) {
+                               setPublicKey(transfer.getFileKey());
+                               update();
+                       }
+
+                       if(transfer.isFinished() && transfer.isSuccessful()) {
+                               transfer = null;
+                       }
+
+                       setChanged();
+                       notifyObservers();
+               }
+       }
+
+       public int getId() {
+               return id;
+       }
+
+       
+       public Element getXML(Document xmlDoc) {
+               if(getPublicKey() == null)
+                       return null;
+
+               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(Iterator it = getOptionElements(xmlDoc).iterator();
+                   it.hasNext(); ) {
+                       Element e = (Element)it.next();
+                       file.appendChild(e);
+               }
+
+               return file;
+       }
+
+       /**
+        * @return Element Vector
+        */
+       public Vector getOptionElements(Document xmlDoc) {
+               Vector options = new Vector();
+
+               if(category != null) {
+                       Element categoryEl = xmlDoc.createElement("option");
+                       categoryEl.setAttribute("name", "category");
+                       categoryEl.setAttribute("value", category);
+
+                       options.add(categoryEl);
+               }
+
+               return options;
+       }
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/FileCategory.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileCategory.java    2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileCategory.java    2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,23 @@
+package thaw.plugins.index;
+
+import java.sql.*;
+
+import thaw.fcp.*;
+import thaw.plugins.Hsqldb;
+
+public class FileCategory {
+
+       public FileCategory() {
+
+       }
+
+       /**
+        * TODO !
+        */
+       public static String promptForACategory() {
+               return null;
+       }
+
+
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/FileDetailsEditor.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileDetailsEditor.java       
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileDetailsEditor.java       
2006-08-21 03:09:08 UTC (rev 10221)
@@ -0,0 +1,20 @@
+package thaw.plugins.index;
+
+
+import javax.swing.JPanel;
+
+public class FileDetailsEditor {
+       
+       private JPanel panel;
+
+       public FileDetailsEditor(boolean modifiables) {
+               panel = new JPanel();
+       }
+
+
+       public JPanel getPanel() {
+               return panel;
+       }
+
+}
+

Added: trunk/apps/Thaw/src/thaw/plugins/index/FileList.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileList.java        2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileList.java        2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,29 @@
+package thaw.plugins.index;
+
+import java.util.Vector;
+
+/**
+ * List files, but also links.
+ */
+public interface FileList {
+
+       public void loadLists(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);
+
+       /**
+        * Must returns a copy of the vector it's using !
+        */
+       public Vector getLinkList();
+
+       /**
+        * Can update the database.
+        */
+       public void unloadLists();
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java       2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/FileTable.java       2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,441 @@
+package thaw.plugins.index;
+
+import javax.swing.JPanel;
+import javax.swing.JTable;
+import javax.swing.JScrollPane;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import javax.swing.event.TableModelListener;
+import javax.swing.event.TableModelEvent;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.KeyEvent;
+
+import javax.swing.table.DefaultTableCellRenderer;
+import java.awt.Component;
+
+import javax.swing.JPopupMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JFileChooser;
+import javax.swing.JProgressBar;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.StringSelection;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+import java.util.Observable;
+import java.util.Observer;
+
+import thaw.core.*;
+import thaw.fcp.*;
+
+public class FileTable implements MouseListener, KeyListener, ActionListener {
+       
+       private JTable table;
+       private FileListModel fileListModel;
+
+       private JPanel panel;
+
+       private FileList fileList = null;
+
+       private boolean modifiables;
+       
+       private JPopupMenu rightClickMenu;
+       private JMenuItem removeFiles;
+       private JMenuItem insertFiles;
+       private JMenuItem recalculateKeys;
+
+       private JMenuItem downloadFiles;
+       
+       private JMenuItem copyFileKeys;
+
+       private FCPQueueManager queueManager;
+
+       private int[] selectedRows;
+
+       public FileTable(boolean modifiables, FCPQueueManager queueManager) {
+               this.queueManager = queueManager;
+               panel = new JPanel();
+               panel.setLayout(new BorderLayout(10, 10));
+
+               this.modifiables = modifiables;
+
+               
+               
+               rightClickMenu = new JPopupMenu();
+               
+               if(modifiables) {
+                       removeFiles = new 
JMenuItem(I18n.getMessage("thaw.common.remove"));
+                       insertFiles = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.insert"));
+                       recalculateKeys = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.recalculateKeys"));
+                       removeFiles.addActionListener(this);
+                       insertFiles.addActionListener(this);
+                       recalculateKeys.addActionListener(this);
+                       rightClickMenu.add(removeFiles);
+                       rightClickMenu.add(insertFiles);
+                       rightClickMenu.add(recalculateKeys);
+               } else {
+                       downloadFiles   = new 
JMenuItem(I18n.getMessage("thaw.common.action.download"));
+                       downloadFiles.addActionListener(this);
+                       rightClickMenu.add(downloadFiles);
+               }
+
+               copyFileKeys = new 
JMenuItem(I18n.getMessage("thaw.common.copyKeysToClipboard"));
+               copyFileKeys.addActionListener(this);
+               rightClickMenu.add(copyFileKeys);
+
+               fileListModel = new FileListModel();
+               table = new JTable(fileListModel);
+               table.setShowGrid(true);
+               table.setDefaultRenderer( table.getColumnClass(0), new 
FileRenderer() );
+
+               table.addMouseListener(this);
+
+       }
+
+
+       public JScrollPane getPanel() {
+               return new JScrollPane(table);
+       }
+
+       
+       public void setFileList(FileList fileList) {
+               if(this.fileList != null) {
+                       this.fileList.unloadLists();
+               }
+               
+               if(fileList != null) {
+                       fileList.loadLists(null, true);
+               }
+
+               this.fileList = fileList;
+
+               fileListModel.reloadFileList(fileList);
+       }
+
+
+       public void mouseClicked(MouseEvent e) {
+               if(e.getButton() == MouseEvent.BUTTON3
+                  && fileList != null
+                  && fileList instanceof Index) {
+                       selectedRows = table.getSelectedRows();
+                       rightClickMenu.show(e.getComponent(), e.getX(), 
e.getY());
+               }
+       }
+
+       public void mouseEntered(MouseEvent e) { }
+
+       public void mouseExited(MouseEvent e) { }
+
+       public void mousePressed(MouseEvent e) { }
+
+       public void mouseReleased(MouseEvent e) { }
+
+       public void keyPressed(KeyEvent e) { }
+
+       public void keyReleased(KeyEvent e) { }
+
+       public void keyTyped(KeyEvent e) { }
+
+       public void actionPerformed(ActionEvent e) {
+               if(fileList == null
+                  || !(fileList instanceof Index))
+                       return;
+
+               String keys = "";
+               
+               Vector files = null;
+
+               Index index = (Index)fileList;
+
+               java.io.File destination = null;
+
+               if(e.getSource() == downloadFiles) {
+                       FileChooser fileChooser = new FileChooser();
+                       
fileChooser.setTitle(I18n.getMessage("thaw.plugin.fetch.destinationDirectory"));
+                       fileChooser.setDirectoryOnly(true);
+                       fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
+                       
+                       destination = fileChooser.askOneFile();
+
+                       if(destination == null)
+                               return;
+               }
+
+               if(e.getSource() == removeFiles) {
+                       files = fileList.getFileList();
+               }
+
+               for(int i = 0 ; i < selectedRows.length ; i++) {
+
+                       if(e.getSource() == removeFiles) {
+                               
index.removeFile((thaw.plugins.index.File)files.get(selectedRows[i]));
+                       }
+                       
+                       if(e.getSource() == insertFiles) {
+                               thaw.plugins.index.File file = 
index.getFile(selectedRows[i]);
+                               
+                               FCPClientPut clientPut = new FCPClientPut(new 
java.io.File(file.getLocalPath()),
+                                                                         0, 0, 
null, null, 4, true, 0);
+                               
queueManager.addQueryToThePendingQueue(clientPut);
+                               
+                               file.setTransfer(clientPut);
+                       }
+                       
+                       
+                       if(e.getSource() == downloadFiles) {
+                               thaw.plugins.index.File file = 
index.getFile(selectedRows[i]);
+
+                               FCPClientGet clientGet = new 
FCPClientGet(file.getPublicKey(), 4, 0, true,
+                                                                         
destination.getPath());
+
+                               
queueManager.addQueryToThePendingQueue(clientGet);
+                               
+                               file.setTransfer(clientGet);
+                       }
+
+                       if(e.getSource() == copyFileKeys) {
+                               thaw.plugins.index.File file = 
index.getFile(selectedRows[i]);
+                               if(file.getPublicKey() != null)
+                                       keys = keys + file.getPublicKey() + 
"\n";
+                       }
+
+                       if(e.getSource() == recalculateKeys) {
+                               thaw.plugins.index.File file = 
index.getFile(selectedRows[i]);
+
+                               FCPClientPut insertion = new FCPClientPut(new 
java.io.File(file.getLocalPath()), 0, 0, null,
+                                                                         null, 
4,
+                                                                         true, 
2, true); /* getCHKOnly */
+                               insertion.start(queueManager);
+
+                               file.setTransfer(insertion);
+                       }
+
+               }
+
+               if(e.getSource() == copyFileKeys) {
+                       Toolkit tk = Toolkit.getDefaultToolkit();
+                       StringSelection st = new StringSelection(keys);
+                       Clipboard cp = tk.getSystemClipboard();
+                       cp.setContents(st, null);
+               }
+       }
+       
+
+       public class FileListModel extends javax.swing.table.AbstractTableModel 
implements java.util.Observer {
+               public Vector columnNames;
+
+               public Vector files = null; /* thaw.plugins.index.File Vector */
+
+               public FileList fileList;
+
+               public FileListModel() {
+                       super();
+
+                       columnNames = new Vector();
+
+                       columnNames.add(I18n.getMessage("thaw.common.file"));
+                       columnNames.add(I18n.getMessage("thaw.common.size"));
+                       
+                       if(modifiables)
+                               
columnNames.add(I18n.getMessage("thaw.common.localPath"));
+
+                       
columnNames.add(I18n.getMessage("thaw.plugin.index.category"));
+                       columnNames.add(I18n.getMessage("thaw.common.key"));
+                       columnNames.add(I18n.getMessage("thaw.common.status"));
+               }
+
+               public void reloadFileList(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(Iterator it = files.iterator();
+                                   it.hasNext(); ) {
+                                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                                       file.deleteObserver(this);
+                               }
+                       }
+
+                       files = null;
+                       
+                       if(fileList != null) {
+                               files = fileList.getFileList();
+                       }
+
+                       if(files != null) {
+                               for(Iterator it = files.iterator();
+                                   it.hasNext(); ) {
+                                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                                       file.addObserver(this);
+                               }
+
+                       }       
+
+                       refresh();
+               }
+
+               public int getRowCount() {
+                       if(files == null)
+                               return 0;
+
+                       return files.size();
+               }
+
+               public int getColumnCount() {
+                       return columnNames.size();
+               }
+
+               public String getColumnName(int column) {
+                       return (String)columnNames.get(column);
+               }
+
+               public Object getValueAt(int row, int column) {
+                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)files.get(row);
+
+                       if(column == 0)
+                               return file.getFilename();
+
+                       if(column == 1)
+                               return new Long(file.getSize());
+
+                       if(column == 2 && modifiables)
+                               return file.getLocalPath();
+
+                       if( (column == 2 && !modifiables)
+                           || (column == 3 && modifiables) )
+                               return file.getCategory();
+
+                       if( (column == 3 && !modifiables)
+                           || (column == 4 && modifiables) )
+                               return file.getPublicKey();
+
+                       if( (column == 4 && !modifiables)
+                           || (column == 5 && modifiables) ) {
+                               return file.getTransfer();
+                       }
+
+                       return null;
+               }
+
+               public void refresh() {
+                       if(fileList != null) {                          
+                               files = fileList.getFileList();
+                       }
+
+                       TableModelEvent event = new TableModelEvent(this);
+                       refresh(event);
+               }
+
+               public void refresh(int row) {
+                       TableModelEvent event = new TableModelEvent(this, row);
+                       refresh(event);
+               }
+
+               public void refresh(TableModelEvent e) {
+
+                       fireTableChanged(e);
+                       /*
+                       TableModelListener[] listeners = 
getTableModelListeners();
+
+                       for(int i = 0 ; i < listeners.length ; i++) {
+                               listeners[i].tableChanged(e);
+                       }
+                       */
+               }
+
+               public void update(java.util.Observable o, Object param) {
+                       if(param instanceof thaw.plugins.index.File) {
+
+                               /* TODO : It can be a remove ... to check ... */
+
+                               thaw.plugins.index.File file = 
(thaw.plugins.index.File)param;
+                               
+                               file.deleteObserver(this);
+                               file.addObserver(this);
+                       }
+
+                       refresh(); /* TODO : Do it more nicely ... :) */
+               }
+       }
+
+
+       private class FileRenderer extends DefaultTableCellRenderer {
+               private final static long serialVersionUID = 20060821;
+               
+               public FileRenderer() {
+
+               }
+
+               public Component getTableCellRendererComponent(JTable table, 
Object value,
+                                                              boolean 
isSelected, boolean hasFocus,
+                                                              int row, int 
column) {
+
+                       if(value == null)
+                               return 
super.getTableCellRendererComponent(table, "",
+                                                                          
isSelected, hasFocus, row, column);
+
+                       if(value instanceof FCPTransferQuery) {
+                               FCPTransferQuery query = 
(FCPTransferQuery)value;
+                               JProgressBar bar = new JProgressBar(0, 100);
+
+                               bar.setStringPainted(true);
+                               bar.setBorderPainted(false);
+                               
+                               if((query instanceof FCPClientPut && 
query.getProgression() > 0)
+                                  || (query instanceof FCPClientGet && 
query.getProgression() < 100) )
+                                       bar.setValue(query.getProgression());
+                               else
+                                       
bar.setValue(query.getTransferWithTheNodeProgression());
+                               
+                               if(query.isFinished() && !query.isSuccessful())
+                                       
bar.setString(I18n.getMessage("thaw.common.failed"));
+
+                               if(query.isFinished() && query.isSuccessful())
+                                       
bar.setString(I18n.getMessage("thaw.common.ok"));
+
+                               if(!query.isFinished()) {
+                                       if(query instanceof FCPClientGet)
+                                               
bar.setString(I18n.getMessage("thaw.common.downloading"));
+                                       else
+                                               
bar.setString(I18n.getMessage("thaw.common.uploading"));
+                               }
+
+                               return bar;
+                       }
+                       
+                       if(value instanceof Long) {
+                               return 
super.getTableCellRendererComponent(table,
+                                                                          
thaw.plugins.queueWatcher.QueueTableModel.getPrintableSize(((Long)value).longValue()),
+                                                                          
isSelected, hasFocus, row, column);
+                       }
+
+                       Component cell = 
super.getTableCellRendererComponent(table, value,
+                                                                            
isSelected, hasFocus,
+                                                                            
row, column);
+
+                       return cell;
+               }
+
+       }
+
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/Index.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -0,0 +1,659 @@
+package thaw.plugins.index;
+
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import java.sql.*;
+
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Iterator;
+
+import org.w3c.dom.Document;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import org.w3c.dom.DOMImplementation;
+import javax.xml.transform.stream.StreamResult;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.OutputKeys;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.io.OutputStream;
+import java.io.FileOutputStream;
+
+import thaw.fcp.*;
+import thaw.plugins.Hsqldb;
+import thaw.core.*;
+
+public class Index extends java.util.Observable implements FileList, 
IndexTreeNode, java.util.Observer {
+
+       private Hsqldb db;
+       private IndexTree tree;
+
+       private int id;
+       private IndexCategory parent;
+       private String realName;
+       private String displayName;
+       private boolean modifiable;
+       
+       private String publicKey; /* without the filename ! */
+       private String privateKey;
+
+       private int revision = 0;
+
+       private Vector fileList;
+
+       private DefaultMutableTreeNode treeNode;
+
+       private FCPGenerateSSK sskGenerator;
+
+       private FCPQueueManager queueManager;
+
+       private FCPTransferQuery transfer = null;
+       private java.io.File targetFile = null;
+
+       public Index(Hsqldb db, FCPQueueManager queueManager,
+                    int id, IndexCategory parent,
+                    String realName, String displayName,
+                    String publicKey, String privateKey,
+                    int revision,
+                    boolean modifiable) {
+               this.queueManager = queueManager;
+
+               treeNode = new DefaultMutableTreeNode(displayName, false);
+
+               this.db = db;
+               this.tree = tree;
+
+               this.id = id;
+               this.parent = parent;
+               this.realName = realName;
+               this.displayName = displayName;
+               this.modifiable = modifiable;
+
+               this.publicKey = publicKey;
+
+               this.privateKey = privateKey;
+
+               this.revision = revision;
+
+               treeNode.setUserObject(this);
+       }
+
+       public DefaultMutableTreeNode getTreeNode() {
+               return treeNode;
+       }
+
+       public void generateKeys(FCPQueueManager queueManager) {
+               publicKey = "N/A";
+               privateKey = "N/A";
+
+               sskGenerator = new FCPGenerateSSK();
+               sskGenerator.addObserver(this);
+               sskGenerator.start(queueManager);
+       }
+
+       public boolean create() {
+               try {
+                       /* Rahh ! Hsqldb doesn't support getGeneratedKeys() ! 
8/ */
+                       
+                       Connection c = db.getConnection();
+                       PreparedStatement st;
+
+                       st = c.prepareStatement("SELECT id FROM indexes ORDER 
BY id DESC LIMIT 1");
+
+                       st.execute();
+
+                       try {
+                               ResultSet key = st.getResultSet();              
+                               key.next();
+                               id = key.getInt(1) + 1;
+                       } catch(SQLException e) {
+                               id = 1;
+                       }
+
+                       st = c.prepareStatement("INSERT INTO indexes (id, 
originalName, displayName, publicKey, privateKey, positionInTree, revision, 
parent) "+
+                                               "VALUES (?, ?,?,?,?,?,?, ?)");
+                       st.setInt(1, id);
+                       st.setString(2, realName);
+                       st.setString(3, displayName);
+                       st.setString(4, publicKey);
+                       st.setString(5, privateKey);
+                       st.setInt(6, 0);
+
+                       st.setInt(7, revision);
+
+                       if(parent.getId() >= 0)
+                               st.setInt(8, parent.getId());
+                       else
+                               st.setNull(8, Types.INTEGER);
+                       
+                       st.execute();
+                                               
+                       return true;
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to insert the new index in 
the db, because: "+e.toString());
+
+                       return false;
+               }
+
+       }
+
+       public void rename(String name) {
+               try {
+                       Connection c = db.getConnection();
+                       PreparedStatement st;
+
+                       if(!modifiable) {
+                               st = c.prepareStatement("UPDATE indexes SET 
displayName = ? WHERE id = ?");
+                               st.setString(1, name);
+                               st.setInt(2, id);
+                       } else {
+                               st = c.prepareStatement("UPDATE indexes SET 
displayName = ?, originalName = ? WHERE id = ?");
+                               st.setString(1, name);
+                               st.setString(2, name);
+                               st.setInt(3, id);
+                       }
+                       
+                       st.execute();
+
+                       this.displayName = name;
+                       
+                       if(modifiable)
+                               this.realName = name;
+
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to rename the index 
'"+this.displayName+"' in '"+name+"', because: "+e.toString());
+               }
+       }
+
+       public void delete() {
+               try {
+                       loadLists(null, false);
+
+                       for(Iterator fileIt = fileList.iterator();
+                           fileIt.hasNext(); ) {
+                               thaw.plugins.index.File file = 
(thaw.plugins.index.File)fileIt.next();
+                               file.delete();
+                       }
+                           
+
+                       /* TODO : Delete links */
+
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("DELETE FROM 
indexes WHERE id = ?");
+                       st.setInt(1, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to delete the index 
'"+displayName+"', because: "+e.toString());
+               }
+       }
+
+       public void update() {
+               targetFile = new java.io.File(toString()+".xml");
+
+               if(modifiable) {
+                       FCPClientPut clientPut;
+
+                       Logger.info(this, "Generating index ...");
+                       generateXML(targetFile);
+
+                       if(targetFile.exists()) {
+                               Logger.info(this, "Inserting new version");
+                               
+                               revision++;
+
+                               clientPut = new FCPClientPut(targetFile, 2, 
revision, toString(), privateKey, 4, false, 2);
+                               transfer = clientPut;
+                               clientPut.addObserver(this);
+
+                               
queueManager.addQueryToThePendingQueue(clientPut);
+
+                               save();
+
+                       } else {
+                               Logger.warning(this, "Index not generated !");
+                       }
+               } else {
+                       FCPClientGet clientGet;
+                       
+                       Logger.info(this, "Getting last version");
+
+                       clientGet = new FCPClientGet(publicKey, 4, 2, false, 
System.getProperty("java.io.tmpdir"));
+                       transfer = clientGet;
+                       clientGet.addObserver(this);
+
+                       queueManager.addQueryToThePendingQueue(clientGet);
+               }
+
+               setChanged();
+               notifyObservers();
+               
+       }
+
+       public boolean isUpdating() {
+               return (transfer != null && (!transfer.isFinished()));
+       }
+
+       public void purgeLinkList() {
+               /* TODO */
+       }
+       
+       public void purgeFileList() {
+               try {
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("DELETE FROM 
files WHERE indexParent = ?");
+                       st.setInt(1, getId());
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.warning(this, "Unable to purge da list ! 
Exception: "+e.toString());
+               }
+       }
+
+       public void save() {
+               try {
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("UPDATE 
indexes SET originalName = ?, displayName = ?, publicKey = ?, privateKey = ?, 
positionInTree = ?, revision = ?, parent = ? WHERE id = ?");
+
+                       st.setString(1, realName);
+                       st.setString(2, displayName);
+                       st.setString(3, publicKey);
+                       if(privateKey != null)
+                               st.setString(4, privateKey);
+                       else
+                               st.setNull(4, Types.VARCHAR);
+                       st.setInt(5, treeNode.getParent().getIndex(treeNode));
+                       
+                       st.setInt(6, revision);
+
+                       if( ((IndexTreeNode)treeNode.getParent()).getId() < 0)
+                               st.setNull(7, Types.INTEGER);
+                       else
+                               st.setInt(7, 
((IndexTreeNode)treeNode.getParent()).getId());
+                       
+                       st.setInt(8, getId());
+
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to save index state 
'"+toString()+"' because : "+e.toString());
+               }
+       }
+
+       public int getId() {
+               return id;
+       }
+
+       public String getKey() {
+               if(modifiable)
+                       return publicKey.replace("SSK@", 
"USK@")+realName+"/"+revision+"/";
+               else
+                       return publicKey;
+       }
+
+       public String toString() {
+               if(displayName != null)
+                       return displayName;
+               return realName;
+       }
+
+       public boolean isLeaf() {
+               return true;
+       }
+
+       public void update(java.util.Observable o, Object p) {
+               if(o == sskGenerator) {
+                       sskGenerator.deleteObserver(this);
+                       publicKey = sskGenerator.getPublicKey();
+                       privateKey = sskGenerator.getPrivateKey();
+
+                       Logger.debug(this, "Index public key: "+publicKey);
+                       Logger.debug(this, "Index private key: "+privateKey);
+               }
+
+               if(o == transfer) {
+                       if(transfer.isFinished() && transfer.isSuccessful()) {
+
+                               queueManager.remove(transfer);
+
+                               if(transfer instanceof FCPClientPut) {
+                                       targetFile.delete();
+                                       
+                                       transfer = null;
+                                       
+                                       setChanged();
+                                       notifyObservers();
+                                       
+                                       return;
+                               }
+                               
+                               if(transfer instanceof FCPClientGet) {
+                                       java.io.File file = new 
java.io.File(transfer.getPath());
+
+                                       Logger.info(this, "Updating index ...");
+                                       
+                                       loadXML(file);
+                                       save();
+
+                                       Logger.info(this, "Update done.");
+
+                                       file.delete();
+                                       
+                                       transfer = null;
+                                       
+                                       setChanged();
+                                       notifyObservers();
+                                       
+                                       return;
+                               }
+
+                       }
+               }
+       }
+       
+
+       ////// FILE LIST ////////
+
+       public void loadLists(String columnToSort, boolean asc) {
+               fileList = new Vector();
+
+               try {
+                       String query = "SELECT id, publicKey, mime, size, 
localPath, category FROM files WHERE indexParent = ?";
+
+                       if(columnToSort != null) {
+                               query = query + "ORDER BY " + columnToSort;
+
+                               if(!asc)
+                                       query = query + " DESC";
+                       }
+
+                       PreparedStatement st = 
db.getConnection().prepareStatement(query);
+
+                       st.setInt(1, getId());
+
+                       if(st.execute()) {
+                               ResultSet results = st.getResultSet();
+
+                               while(results.next()) {
+                                       thaw.plugins.index.File file = new 
thaw.plugins.index.File(db, results, this);
+                                       fileList.add(file);
+                               }
+                       }
+
+
+               } catch(java.sql.SQLException e) {
+                       Logger.warning(this, "Unable to get the file list for 
index: '"+toString()+"' because: "+e.toString());
+               }
+       }
+
+       /**
+        * Returns a *copy* of da vector.
+        */
+       public Vector getFileList() {
+               Vector newList = new Vector();
+
+               for(Iterator it = fileList.iterator();
+                   it.hasNext();) {
+                       newList.add(it.next());
+               }
+
+               return newList;
+       }
+
+       public thaw.plugins.index.File getFile(int index) {
+               return (thaw.plugins.index.File)fileList.get(index);
+       }
+
+       public Vector getLinkList() {
+               return null;
+       }
+
+       public void unloadLists() {
+               //updateFileList();
+               fileList = null;
+       }
+
+
+       public void addFile(thaw.plugins.index.File file) {
+               file.setParent(this);
+               file.insert();
+
+               if(fileList != null) {
+                       fileList.add(file);
+
+                       setChanged();
+                       notifyObservers(file);
+               }
+       }
+
+       public void removeFile(thaw.plugins.index.File file) {
+               file.delete();
+
+               if(fileList != null) {
+                       fileList.remove(file);
+
+                       setChanged();
+                       notifyObservers(file);
+               }
+       }
+
+       /**
+        * Do the update all the files in the database.
+        */
+       public void updateFileList() {          
+               for(Iterator it = fileList.iterator();
+                   it.hasNext();) {
+                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+                       file.update();
+               }
+       }
+
+
+       //// XML ////
+
+       public void generateXML(java.io.File file) {
+               
+               FileOutputStream outputStream;
+
+               try {
+                       outputStream = new FileOutputStream(file);
+               } catch(java.io.FileNotFoundException e) {
+                       Logger.warning(this, "Unable to create file '"+file+"' 
! not generated !");
+                       return;
+               }
+
+               generateXML(outputStream);
+
+               try {
+                       outputStream.close();
+               } catch(java.io.IOException e) {
+                       Logger.error(this, "Unable to close stream because: 
"+e.toString());
+               }
+       }
+
+       public void generateXML(OutputStream out) {
+               StreamResult streamResult = new StreamResult(out);
+
+               Document xmlDoc;
+               
+               DocumentBuilderFactory xmlFactory = 
DocumentBuilderFactory.newInstance();
+               DocumentBuilder xmlBuilder;
+
+               try {
+                       xmlBuilder = xmlFactory.newDocumentBuilder();
+               } catch(javax.xml.parsers.ParserConfigurationException e) {
+                       Logger.error(this, "Unable to generate the index 
because : "+e.toString());
+                       return;
+               }
+
+               DOMImplementation impl = xmlBuilder.getDOMImplementation();
+
+               xmlDoc = impl.createDocument(null, "index", null);
+
+               Element rootEl = xmlDoc.getDocumentElement();
+
+               rootEl.appendChild(getXMLHeader(xmlDoc));
+               rootEl.appendChild(getXMLLinks(xmlDoc));
+               rootEl.appendChild(getXMLFileList(xmlDoc));
+               
+               /* Serialization */
+               DOMSource domSource = new DOMSource(xmlDoc);
+               TransformerFactory transformFactory = 
TransformerFactory.newInstance();
+
+               Transformer serializer;
+
+               try {
+                       serializer = transformFactory.newTransformer();
+               } catch(javax.xml.transform.TransformerConfigurationException 
e) {
+                       Logger.error(this, "Unable to save index because: 
"+e.toString());
+                       return;
+               }
+
+               serializer.setOutputProperty(OutputKeys.ENCODING,"ISO-8859-1");
+               serializer.setOutputProperty(OutputKeys.INDENT,"yes");
+               
+               /* final step */
+               try {
+                       serializer.transform(domSource, streamResult);
+               } catch(javax.xml.transform.TransformerException e) {
+                       Logger.error(this, "Unable to save index because: 
"+e.toString());
+                       return;
+               }
+       }
+
+       public Element getXMLHeader(Document xmlDoc) {
+               Element header = xmlDoc.createElement("header");
+               
+               Element title = xmlDoc.createElement("title");
+               Text titleText = xmlDoc.createTextNode(toString());             
+               title.appendChild(titleText);
+
+               /* TODO : Allow to change username  + email */
+               Element owner = xmlDoc.createElement("owner");
+               Text ownerText = xmlDoc.createTextNode("Another anonymous");
+               owner.appendChild(ownerText);
+               
+               header.appendChild(title);
+               header.appendChild(owner);
+
+               return header;
+       }
+
+       public Element getXMLLinks(Document xmlDoc) {
+               Element links = xmlDoc.createElement("indexes");
+
+               return links;
+       }
+
+       public Element getXMLFileList(Document xmlDoc) {
+               Element files = xmlDoc.createElement("files");
+
+               if(fileList == null) {
+                       loadLists(null, true);
+               }
+
+               for(Iterator it = getFileList().iterator();
+                   it.hasNext();) {
+                       thaw.plugins.index.File file = 
(thaw.plugins.index.File)it.next();
+
+                       Element xmlFile = file.getXML(xmlDoc);
+
+                       if(xmlFile != null)
+                               files.appendChild(xmlFile);
+                       else
+                               Logger.warning(this, "Public key wasn't 
generated ! Not added to the index !");
+               }
+
+               return files;
+       }
+
+       public void loadXML(java.io.File file) {
+               DocumentBuilderFactory xmlFactory = 
DocumentBuilderFactory.newInstance();
+               DocumentBuilder xmlBuilder;
+
+               try {
+                       xmlBuilder = xmlFactory.newDocumentBuilder();
+               } catch(javax.xml.parsers.ParserConfigurationException e) {
+                       Logger.error(this, "Unable to load index because: 
"+e.toString());
+                       return;
+               }
+               
+               Document xmlDoc;
+
+               try {
+                       xmlDoc = xmlBuilder.parse(file);
+               } catch(org.xml.sax.SAXException e) {
+                       Logger.error(this, "Unable to load index because: 
"+e.toString());
+                       return;
+               } catch(java.io.IOException e) {
+                       Logger.error(this, "Unable to load index because: 
"+e.toString());
+                       return;
+               }
+
+               Element rootEl = xmlDoc.getDocumentElement();
+
+               loadHeader(rootEl);
+               loadLinks(rootEl);
+               loadFileList(rootEl);
+       }
+
+
+       public void loadHeader(Element rootEl) {
+               Element header = 
(Element)rootEl.getElementsByTagName("header").item(0);
+
+               realName = getHeaderElement(header, "title");
+               
+               /* TODO : Author */
+       }
+
+       public String getHeaderElement(Element header, String name) {
+               try {
+                       Element sub = 
(Element)header.getElementsByTagName(name).item(0);
+                       return ((Text)sub.getFirstChild()).getData();
+               } catch(Exception e) {
+                       Logger.notice(this, "Unable to get header element 
'"+name+"', because: "+e.toString());
+                       return null;
+               }
+       }
+
+       public void loadLinks(Element rootEl) {
+               purgeLinkList();
+
+               Element links = 
(Element)rootEl.getElementsByTagName("indexes").item(0);
+               NodeList list = links.getChildNodes();
+
+               for(int i = 0; i < list.getLength() ; i++) {
+                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
+                               Element e = (Element)list.item(i);
+                               
+                               /* TODO : Links */
+                       }
+               }
+               
+       }
+
+       public void loadFileList(Element rootEl) {
+               fileList = new Vector();
+               purgeFileList();
+
+               Element filesEl = 
(Element)rootEl.getElementsByTagName("files").item(0);
+               NodeList list = filesEl.getChildNodes();
+
+               for(int i = 0; i < list.getLength() ; i++) {
+                       if(list.item(i).getNodeType() == Node.ELEMENT_NODE) {
+                               Element e = (Element)list.item(i);
+                               
+                               thaw.plugins.index.File file = new 
thaw.plugins.index.File(db, e, this);
+                               addFile(file);
+                       }
+               }
+       }
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java       
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexBrowserPanel.java       
2006-08-21 03:09:08 UTC (rev 10221)
@@ -0,0 +1,106 @@
+package thaw.plugins;
+
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import javax.swing.JToolBar;
+import javax.swing.JButton;
+
+import javax.swing.JFileChooser;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import thaw.core.*;
+import thaw.fcp.*;
+
+import thaw.plugins.index.*;
+
+
+public class IndexBrowserPanel implements 
javax.swing.event.TreeSelectionListener, ActionListener {
+       public final static int DEFAULT_INSERTION_PRIORITY = 4;
+
+       private IndexTree indexTree;
+
+       private JSplitPane split;
+
+       private JPanel listAndDetails;
+       private FileTable fileTable;
+       private FileDetailsEditor fileDetails;
+
+       private FileList fileList = null;
+       
+       private Hsqldb db;
+       private FCPQueueManager queueManager;
+
+
+       public IndexBrowserPanel(Hsqldb db, FCPQueueManager queueManager) {
+               this.db = db;
+               this.queueManager = queueManager;
+
+               indexTree = new 
IndexTree(I18n.getMessage("thaw.plugin.index.indexes"), false, queueManager, 
db);
+
+               listAndDetails = new JPanel();
+               listAndDetails.setLayout(new BorderLayout(10, 10));
+
+               fileTable = new FileTable(false, queueManager);
+               fileDetails = new FileDetailsEditor(false);
+
+               listAndDetails.add(fileTable.getPanel(), BorderLayout.CENTER);
+               listAndDetails.add(fileDetails.getPanel(), BorderLayout.SOUTH);
+
+               split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+                                      indexTree.getPanel(),
+                                      listAndDetails);
+
+               indexTree.addTreeSelectionListener(this);
+
+       }
+
+       public JSplitPane getPanel() {
+               return split;
+       }
+
+       public void save() {
+               indexTree.save();
+       }
+
+       public void setFileList(FileList l) {
+               this.fileList = l;
+               fileTable.setFileList(l);               
+       }
+
+       public void valueChanged(javax.swing.event.TreeSelectionEvent e) {
+               javax.swing.tree.TreePath path = e.getPath();
+               
+               if(path == null) {
+                       Logger.notice(this, "Path null ?");
+                       setFileList(null);
+                       return;
+               }
+               
+               IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+
+               if(node == null) {
+                       Logger.notice(this, "Node null ?");
+                       setFileList(null);
+                       return;
+               }
+
+               if(node instanceof FileList) {
+                       Logger.info(this, "FileList !");
+                       setFileList((FileList)node);
+                       return;
+               }
+               
+               setFileList(null);
+       }
+
+
+       public void actionPerformed(ActionEvent e) {
+
+       }
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java   2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexCategory.java   2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,370 @@
+package thaw.plugins.index;
+
+import java.sql.*;
+
+import javax.swing.JTree;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Iterator;
+
+import java.sql.*;
+
+import thaw.fcp.*;
+import thaw.plugins.Hsqldb;
+
+import thaw.core.*;
+
+public class IndexCategory extends DefaultMutableTreeNode implements 
IndexTreeNode {
+
+       private int id;
+       private IndexCategory parent;
+       private String name;
+       private boolean modifiables;
+
+       private Hsqldb db;
+       private FCPQueueManager queueManager;
+       
+       public IndexCategory(Hsqldb db, FCPQueueManager queueManager,
+                            int id, IndexCategory parent,
+                            String name, 
+                            boolean modifiables) {
+               super(name, true);
+
+               this.id = id;
+               this.name = name;
+               this.parent = parent;
+               this.modifiables = modifiables;
+
+               this.db = db;
+               this.queueManager = queueManager;
+
+               setUserObject(this);
+
+       }
+
+       public DefaultMutableTreeNode getTreeNode() {
+               return this;
+       }
+       
+       /**
+        * Insert the category into the database.
+        */
+       public boolean create() {
+               try {
+                       /* Rahh ! Hsqldb doesn't support getGeneratedKeys() ! 
8/ */
+
+                       Connection c = db.getConnection();
+                       PreparedStatement st;
+
+                       st = c.prepareStatement("SELECT id FROM indexCategories 
ORDER BY id DESC LIMIT 1");
+                       st.execute();
+                       
+                       try {
+                               ResultSet key = st.getResultSet();
+                               key.next();
+                               id = key.getInt(1) + 1;
+                       } catch(SQLException e) {
+                               id = 0;
+                       }
+
+                       st = c.prepareStatement("INSERT INTO indexCategories 
(id, name, positionInTree, modifiableIndexes, parent) "+
+                                                                 "VALUES (?, 
?,?,?,?)");
+
+                       st.setInt(1, id);
+                       st.setString(2, name);
+                       st.setInt(3, 0);
+
+                       st.setBoolean(4, modifiables);
+
+                       if(parent.getId() >= 0)
+                               st.setInt(5, parent.getId());
+                       else
+                               st.setNull(5, Types.INTEGER);
+                       
+                       st.execute();
+
+                       return true;
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to insert the new index 
category in the db, because: "+e.toString());
+
+                       return false;
+               }
+       }
+
+       public void delete() {
+               if(children == null)
+                       children = loadChildren();
+
+               for(Iterator it = children.iterator();
+                   it.hasNext();) {
+                       IndexTreeNode child = (IndexTreeNode)it.next();
+                       child.delete();
+               }
+
+               children = null;
+
+               try {
+                       if(id < 0)
+                               return;
+                       
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("DELETE FROM 
indexCategories WHERE id = ?");
+                       st.setInt(1, id);
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to delete the index category 
'"+name+"', because: "+e.toString());
+               }
+       }
+
+       public void rename(String name) {
+
+               try {
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("UPDATE 
indexCategories SET name = ? WHERE id = ?");
+                       
+                       st.setString(1, name);
+                       st.setInt(2, id);
+
+                       st.execute();
+
+                       this.name = name;
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to rename the index category 
'"+this.name+"' in '"+name+"', because: "+e.toString());
+               }
+       }
+
+       public String getKey() {
+               String result = "";
+               
+               for(Iterator it = children.iterator();
+                   it.hasNext();) {
+                       IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
+                       result = result + node.getKey() + "\n";
+               }
+               
+               return result;
+       }
+
+       public void addObserver(java.util.Observer o) {
+               if(children == null)
+                       children = loadChildren();
+
+               for(Iterator it = children.iterator();
+                   it.hasNext();) {
+                       IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)it.next()).getUserObject();
+                       node.addObserver(o);
+               }
+       }
+
+       public void update() {
+               for (Enumeration e = children() ; e.hasMoreElements() ;) {
+                       
((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement()).getUserObject()).update();
+               }
+       }
+
+       public boolean isUpdating() {
+               for (Enumeration e = children() ; e.hasMoreElements() ;) {
+                       
if(((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement())).isUpdating())
+                               return true;
+               }
+
+               return false;
+       }
+
+       public void save() {
+               saveThis();
+
+               for (Enumeration e = children() ; e.hasMoreElements() ;) {
+                       
((IndexTreeNode)((DefaultMutableTreeNode)e.nextElement()).getUserObject()).save();
+               }
+       }
+
+
+       public void saveThis() {
+               if(getId() < 0)
+                       return;
+
+               try {
+                       Connection c = db.getConnection();
+                       PreparedStatement st = c.prepareStatement("UPDATE 
indexCategories SET name = ?, positionInTree = ?, modifiableIndexes = ?, parent 
= ? WHERE id = ?");
+
+                       st.setString(1, name);
+                       st.setInt(2, getParent().getIndex(this));
+                       
+                       st.setBoolean(3, modifiables);
+
+                       if( ((IndexTreeNode)getParent()).getId() < 0)
+                               st.setNull(4, Types.INTEGER);
+                       else
+                               st.setInt(4, 
((IndexTreeNode)getParent()).getId());
+                       
+                       st.setInt(5, getId());
+
+                       st.execute();
+               } catch(SQLException e) {
+                       Logger.error(this, "Unable to save index category state 
'"+toString()+"' because : "+e.toString());
+               }
+       }
+
+       public int getId() {
+               return id;
+       }
+
+       public Vector loadChildren() {
+               Vector children = new Vector();
+
+               Logger.debug(this, "loadChildren()");
+
+               loadChildCategories(children);
+               loadChildIndexes(children);
+
+               cleanChildList(children);
+               
+               Logger.debug(this, "Children: "+children.size());
+
+               for(Iterator it = children.iterator();
+                   it.hasNext(); ) {
+                       add((MutableTreeNode)it.next());
+               }
+
+               return children;
+       }
+
+
+       public void loadChildIndexes(Vector children) {
+
+               ResultSet result;
+
+               String query;
+
+               query = "SELECT id, originalName, displayName, publicKey, 
privateKey, positionInTree, revision FROM indexes";
+
+               if(id < 0)
+                       query = query + " WHERE parent IS NULL";
+               else
+                       query = query + " WHERE parent = "+Integer.toString(id);
+
+               if(modifiables) {
+                       query = query + " AND privateKey IS NOT NULL";
+               } else {
+                       query = query + " AND privateKey IS NULL";
+               }
+
+               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()) {
+                               int id = result.getInt("id");
+                               int position = result.getInt("positionInTree");
+
+                               String realName = 
result.getString("originalName");
+                               String displayName = 
result.getString("displayName");
+
+                               String publicKey = 
result.getString("publicKey");
+                               String privateKey = 
result.getString("privateKey");
+                               
+                               int revision = result.getInt("revision");
+
+                               set(children, position, (new Index(db, 
queueManager, id, this,
+                                                                  realName, 
displayName,
+                                                                  publicKey, 
privateKey, revision,
+                                                                  
modifiables)).getTreeNode());
+                       }
+               } catch (java.sql.SQLException e) {
+                       Logger.warning(this, "SQLException while getting child 
of index category '"+name+"': "+e.toString());
+               }
+
+       }
+
+       public void loadChildCategories(Vector children) {
+               
+               ResultSet result;
+               
+               String query;
+
+               query = "SELECT id, name, positionInTree, modifiableIndexes 
FROM indexCategories";
+
+               if(id < 0)
+                       query = query + " WHERE parent IS NULL";
+               else
+                       query = query + " WHERE parent = "+Integer.toString(id);
+
+               if(modifiables) {
+                       query = query + " AND modifiableIndexes = TRUE";
+               } else {
+                       query = query + " AND modifiableIndexes = FALSE";
+               }
+
+               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()) {
+                               int id = result.getInt("id");
+                               int position = result.getInt("positionInTree");
+                               String name = result.getString("name");
+                               
+                               IndexCategory cat = new IndexCategory(db, 
queueManager, id, this, name, modifiables);
+                               cat.loadChildren();
+                               set(children, position, cat);
+                       }
+               } catch (java.sql.SQLException e) {
+                       Logger.error(this, "SQLException while getting child of 
index category '"+name+"': "+e.toString());
+               }
+
+       }
+
+       protected void cleanChildList(Vector children) {
+               while(children.remove(null)) {
+                       Logger.warning(this, "cleanChildList() : null removed 
!");
+               }
+       }
+
+       public void set(Vector children, int position, TreeNode node) {
+               if(node == this || node == null)
+                       return;
+
+               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 boolean isLeaf() {
+               return false;
+       }
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexEditorPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexEditorPanel.java        
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexEditorPanel.java        
2006-08-21 03:09:08 UTC (rev 10221)
@@ -0,0 +1,188 @@
+package thaw.plugins;
+
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+import javax.swing.JToolBar;
+import javax.swing.JButton;
+
+import javax.swing.JFileChooser;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import thaw.core.*;
+import thaw.fcp.*;
+
+import thaw.plugins.index.*;
+
+
+public class IndexEditorPanel implements java.util.Observer, 
javax.swing.event.TreeSelectionListener, ActionListener {
+       public final static int DEFAULT_INSERTION_PRIORITY = 4;
+
+       private IndexTree indexTree;
+
+       private JSplitPane split;
+
+       private JPanel listAndDetails;
+       private FileTable fileTable;
+       private FileDetailsEditor fileDetails;
+
+       private JToolBar toolBar;
+       private JButton addButton;
+       private JButton insertAndAddButton;
+       
+       private FileList fileList = null;
+       
+       private Hsqldb db;
+       private FCPQueueManager queueManager;
+
+
+       public IndexEditorPanel(Hsqldb db, FCPQueueManager queueManager) {
+               this.db = db;
+               this.queueManager = queueManager;
+
+               indexTree = new 
IndexTree(I18n.getMessage("thaw.plugin.index.yourIndexes"), true, queueManager, 
db);
+
+               listAndDetails = new JPanel();
+               listAndDetails.setLayout(new BorderLayout(10, 10));
+
+               fileTable = new FileTable(true, queueManager);
+               fileDetails = new FileDetailsEditor(true);
+
+               toolBar = new JToolBar();
+               toolBar.setFloatable(false);
+
+               addButton = new JButton(IconBox.addToIndexAction);
+               
addButton.setToolTipText(I18n.getMessage("thaw.plugin.index.addFilesWithoutInserting"));
+               insertAndAddButton = new 
JButton(IconBox.insertAndAddToIndexAction);
+               
insertAndAddButton.setToolTipText(I18n.getMessage("thaw.plugin.index.addFilesWithInserting"));
+
+               addButton.addActionListener(this);
+               insertAndAddButton.addActionListener(this);
+
+               buttonsEnabled(false);
+
+               toolBar.add(addButton);
+               toolBar.add(insertAndAddButton);
+
+               listAndDetails.add(toolBar, BorderLayout.NORTH);
+               listAndDetails.add(fileTable.getPanel(), BorderLayout.CENTER);
+               listAndDetails.add(fileDetails.getPanel(), BorderLayout.SOUTH);
+
+               split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
+                                      indexTree.getPanel(),
+                                      listAndDetails);
+
+               indexTree.addTreeSelectionListener(this);
+
+       }
+
+       public JSplitPane getPanel() {
+               return split;
+       }
+
+       public void save() {
+               indexTree.save();
+       }
+
+       public void buttonsEnabled(boolean a) {
+               addButton.setEnabled(a);
+               insertAndAddButton.setEnabled(a);
+       }
+
+       public void setFileList(FileList l) {
+               buttonsEnabled(l != null && l instanceof Index);
+
+               this.fileList = l;
+               fileTable.setFileList(l);               
+       }
+
+       public void valueChanged(javax.swing.event.TreeSelectionEvent e) {
+               javax.swing.tree.TreePath path = e.getPath();
+               
+               if(path == null) {
+                       Logger.notice(this, "Path null ?");
+                       setFileList(null);
+                       return;
+               }
+               
+               IndexTreeNode node = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+
+               if(node == null) {
+                       Logger.notice(this, "Node null ?");
+                       setFileList(null);
+                       return;
+               }
+
+               if(node instanceof FileList) {                  
+                       setFileList((FileList)node);
+                       return;
+               }
+               
+               setFileList(null);
+       }
+
+
+       public void actionPerformed(ActionEvent e) {
+               if(e.getSource() == addButton
+                  || e.getSource() == insertAndAddButton) {
+                       FileChooser fileChooser = new FileChooser();
+                       
+                       if(e.getSource() == addButton)
+                               
fileChooser.setTitle(I18n.getMessage("thaw.plugin.index.addFilesWithInserting"));
+                       if(e.getSource() == insertAndAddButton)
+                               
fileChooser.setTitle(I18n.getMessage("thaw.plugin.index.addFilesWithoutInserting"));
+
+                       fileChooser.setDirectoryOnly(false);
+                       fileChooser.setDialogType(JFileChooser.OPEN_DIALOG);
+                       
+                       java.io.File[] files = fileChooser.askManyFiles();
+
+                       if(files == null) {
+                               Logger.info(this, "add[andInsert]Button : 
Cancelled");
+                               return;
+                       }
+
+                       String category = FileCategory.promptForACategory();
+
+                       for(int i = 0 ; i < files.length ; i++) {
+                               FCPTransferQuery insertion = null;
+
+                               if(e.getSource() == insertAndAddButton) {
+                                       insertion = new FCPClientPut(files[i], 
0, 0, null,
+                                                                    null, 
DEFAULT_INSERTION_PRIORITY,
+                                                                    true, 0, 
false);
+                                       
((FCPClientPut)insertion).addObserver(this);
+                                       
queueManager.addQueryToThePendingQueue(insertion);
+                               } else {
+                                       insertion = new FCPClientPut(files[i], 
0, 0, null,
+                                                                    null, 
DEFAULT_INSERTION_PRIORITY,
+                                                                    true, 2, 
true); /* getCHKOnly */
+                                       insertion.start(queueManager);
+                               }
+
+
+                               thaw.plugins.index.File file = new 
thaw.plugins.index.File(db, files[i].getPath(),
+                                                                               
           category, (Index)fileList,
+                                                                               
           insertion);
+                               
+                               ((Index)fileList).addFile(file);
+                       }
+               }
+       }
+
+
+       public void update(java.util.Observable o, Object param) {
+               if(o instanceof FCPClientPut) {
+                       FCPClientPut clientPut = (FCPClientPut)o;
+                       if(clientPut.isFinished()) {
+                               queueManager.remove(clientPut);
+                               
+                       }
+               }
+       }
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java       2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexTree.java       2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,387 @@
+package thaw.plugins.index;
+
+import javax.swing.JPanel;
+import java.awt.BorderLayout;
+import javax.swing.JTree;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import javax.swing.JPopupMenu;
+import javax.swing.JMenuItem;
+//import javax.swing.JMenu;
+import javax.swing.JRadioButtonMenuItem;
+
+import javax.swing.JOptionPane;
+
+import javax.swing.JScrollPane;
+
+import javax.swing.Icon;
+
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.StringSelection;
+
+import java.util.Enumeration;
+
+import java.awt.Color;
+
+import thaw.plugins.Hsqldb;
+import thaw.core.*;
+import thaw.fcp.*;
+
+import thaw.gui.JDragTree;
+
+/**
+ * Manages the index tree and its menu (right-click).
+ */
+public class IndexTree implements MouseListener, ActionListener, 
java.util.Observer {
+       
+       private JPanel panel;
+
+       private JDragTree tree;
+       private IndexCategory root;
+
+       private JPopupMenu indexCategoryMenu;
+       private JPopupMenu indexMenu;
+
+       private JMenuItem addIndex;
+       private JMenuItem addIndexCategory;
+       private JMenuItem renameIndexCategory;
+       private JMenuItem renameIndex;
+       private JMenuItem deleteIndexCategory;
+       private JMenuItem deleteIndex;
+       private JMenuItem updateIndexCategory;
+       private JMenuItem updateIndex;
+       private JMenuItem copyKeys;
+       private JMenuItem copyKey;
+       
+       private boolean modifiables;
+
+       private IndexTreeNode selectedNode;
+
+       private DefaultTreeModel treeModel;
+
+       private Hsqldb db;
+       private FCPQueueManager queueManager;
+
+       /**
+        * Menu is defined according to the 'modifiables' parameters.
+        * @param modifiables If set to true, then only indexes having private 
keys will
+        *                    be displayed else only indexes not having private 
keys will
+        *                    be displayed.
+        */
+       public IndexTree(String name,
+                        boolean modifiables,
+                        FCPQueueManager queueManager,
+                        Hsqldb db) {
+               this.queueManager = queueManager;
+
+               this.db = db;
+               this.modifiables = modifiables;
+
+               panel = new JPanel();
+               panel.setLayout(new BorderLayout(10, 10));
+               
+               indexCategoryMenu = new JPopupMenu();
+               indexMenu = new JPopupMenu();
+
+               if(modifiables)
+                       addIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.createIndex"));
+               else
+                       addIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.addIndex"));
+
+               addIndexCategory = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.addCategory"));
+               renameIndexCategory = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.rename"));
+               renameIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.rename"));
+               deleteIndexCategory = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.delete"));
+               deleteIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.delete"));
+               
+               if(modifiables) {
+                       updateIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.insertIndex"));
+                       updateIndexCategory = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.insertIndexes"));
+               } else {
+                       updateIndex = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.downloadIndex"));
+                       updateIndexCategory = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.downloadIndexes"));
+               }
+
+               copyKey = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.copyKey"));
+               copyKeys = new 
JMenuItem(I18n.getMessage("thaw.plugin.index.copyKey"));
+
+               indexCategoryMenu.add(updateIndexCategory);
+               indexCategoryMenu.add(addIndex);
+               indexCategoryMenu.add(addIndexCategory);
+               indexCategoryMenu.add(copyKeys);
+               indexCategoryMenu.add(updateIndex);
+               indexCategoryMenu.add(renameIndexCategory);
+               indexCategoryMenu.add(deleteIndexCategory);
+
+               indexMenu.add(updateIndex);
+               indexMenu.add(copyKey);
+               indexMenu.add(renameIndex);
+               indexMenu.add(deleteIndex);
+
+               addIndex.addActionListener(this);
+               addIndexCategory.addActionListener(this);
+               renameIndexCategory.addActionListener(this);
+               deleteIndexCategory.addActionListener(this);
+               updateIndexCategory.addActionListener(this);
+
+               updateIndex.addActionListener(this);
+               copyKey.addActionListener(this);
+               copyKeys.addActionListener(this);
+               renameIndex.addActionListener(this);
+               deleteIndex.addActionListener(this);
+               
+
+               root = new IndexCategory(db, queueManager, -1, null, name, 
modifiables);
+               root.loadChildren();
+
+               root.addObserver(this);
+
+               treeModel = new DefaultTreeModel(root);
+               tree = new JDragTree(treeModel);
+               tree.addMouseListener(this);
+
+               IndexTreeRenderer treeRenderer = new IndexTreeRenderer();
+               treeRenderer.setLeafIcon(IconBox.minIndex);
+
+               tree.setCellRenderer(treeRenderer);
+
+               panel.add(new JScrollPane(tree));
+       }
+
+
+       public javax.swing.JComponent getPanel() {
+               return panel;
+       }
+
+       public void 
addTreeSelectionListener(javax.swing.event.TreeSelectionListener tsl) {
+               tree.addTreeSelectionListener(tsl);
+       }
+
+
+       public JTree getTree() {
+               return tree;
+       }
+
+
+       public void mouseClicked(MouseEvent e) { }
+       public void mouseEntered(MouseEvent e) { }
+       public void mouseExited(MouseEvent e) { }
+
+       public void mousePressed(MouseEvent e) {
+               showPopupMenu(e);
+       }
+
+       public void mouseReleased(MouseEvent e) {
+               showPopupMenu(e);
+       }
+
+       protected void showPopupMenu(MouseEvent e) {
+               if(e.isPopupTrigger()) {
+                       TreePath path = tree.getPathForLocation(e.getX(), 
e.getY());
+                       
+                       if(path == null)
+                               return;
+
+                       selectedNode = 
(IndexTreeNode)((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+
+                       if(selectedNode == null)
+                               return;
+
+                       if(selectedNode instanceof IndexCategory)
+                               indexCategoryMenu.show(e.getComponent(), 
e.getX(), e.getY());
+                       
+                       if(selectedNode instanceof Index)
+                               indexMenu.show(e.getComponent(), e.getX(), 
e.getY());
+               }
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               if(selectedNode == null)
+                       return;
+
+               if(e.getSource() == addIndex) {
+                       String name = null;
+
+                       String publicKey = null;
+
+                       if(!modifiables) {
+                               publicKey = 
askAName(I18n.getMessage("thaw.plugin.index.indexKey"), "USK@");
+
+                               try {
+                                       publicKey = 
java.net.URLDecoder.decode(publicKey, "UTF-8");
+                               } catch(java.io.UnsupportedEncodingException 
exc) {
+                                       Logger.warning(this, 
"UnsupportedEncodingException (UTF-8): "+exc.toString());
+                               }
+
+                               try {
+                                       String[] cutcut = publicKey.split("/");
+                                       name = cutcut[cutcut.length-2];
+                               } catch(Exception exc) {
+                                       Logger.warning(this, "Error while 
parsing index key: "+publicKey+" because: "+exc.toString() );
+                                       name = publicKey;
+                               }
+                       } else
+                               name = 
askAName(I18n.getMessage("thaw.plugin.index.indexName"),
+                                              
I18n.getMessage("thaw.plugin.index.newIndex"));
+
+                       if(name == null)
+                               return;
+
+                       IndexCategory parent = (IndexCategory)selectedNode;
+
+                       Index index = new Index(db, queueManager, -2, parent, 
name, name, publicKey, null, 0, modifiables);
+
+                       if(modifiables)
+                               index.generateKeys(queueManager);
+
+                       index.create();
+                       parent.insert(index.getTreeNode(), 0);
+
+                       treeModel.reload(parent);
+               }
+
+               if(e.getSource() == addIndexCategory) {
+                       String name = 
askAName(I18n.getMessage("thaw.plugin.index.categoryName"), 
+                                              
I18n.getMessage("thaw.plugin.index.newCategory"));
+
+                       if(name == null)
+                               return;
+
+                       IndexCategory parent = (IndexCategory)selectedNode;
+
+                       /* the id will be defined when created */
+                       IndexCategory cat = new IndexCategory(db, queueManager, 
-2, parent,
+                                                             name, 
modifiables);
+                       cat.create();
+                       parent.insert(cat, 0);
+
+                       treeModel.reload(parent);
+               }
+
+               if(e.getSource() == renameIndexCategory
+                  || e.getSource() == renameIndex) {
+                       
+                       String newName;
+
+                       if(e.getSource() == renameIndexCategory)
+                               newName = 
askAName(I18n.getMessage("thaw.plugin.index.categoryName"), 
+                                                  selectedNode.toString());
+                       else
+                               newName = 
askAName(I18n.getMessage("thaw.plugin.index.indexName"), 
+                                                  selectedNode.toString());
+
+                       if(newName == null)
+                               return;
+
+                       selectedNode.rename(newName);
+
+                       treeModel.reload(selectedNode.getTreeNode());
+               }
+
+               if(e.getSource() == deleteIndexCategory
+                  || e.getSource() == deleteIndex) {
+
+                       MutableTreeNode parent = 
(MutableTreeNode)selectedNode.getTreeNode().getParent();
+
+                       if(parent != null)
+                               parent.remove(selectedNode.getTreeNode());
+
+                       selectedNode.delete();
+
+                       if(parent != null)
+                               treeModel.reload(parent);
+                       else
+                               treeModel.reload();
+               }
+
+               if(e.getSource() == updateIndex
+                  || e.getSource() == updateIndexCategory) {
+                       selectedNode.update();
+               }
+
+               if(e.getSource() == copyKey
+                  || e.getSource() == copyKeys) {
+                       Toolkit tk = Toolkit.getDefaultToolkit();
+                       StringSelection st = new 
StringSelection(selectedNode.getKey());
+                       Clipboard cp = tk.getSystemClipboard();
+                       cp.setContents(st, null);
+               }
+
+       }
+
+       public String askAName(String prompt, String defVal) {
+               return JOptionPane.showInputDialog(prompt, defVal);
+       }
+
+       public void save() {
+               root.save();
+       }
+
+
+       public void update(java.util.Observable o, Object param) {
+               if( (o instanceof Index)
+                   && (param == null) ) {
+                       Index index = (Index)o;
+
+                       treeModel.nodeChanged(index.getTreeNode());
+                       if(index.getTreeNode().getParent() != null)
+                               
treeModel.nodeChanged(index.getTreeNode().getParent());
+
+               }
+       }
+
+
+       public class IndexTreeRenderer extends DefaultTreeCellRenderer {
+
+               public IndexTreeRenderer() {
+                       super();
+               }
+
+               public java.awt.Component getTreeCellRendererComponent(JTree 
tree,
+                                                                      Object 
value,
+                                                                      boolean 
selected,
+                                                                      boolean 
expanded,
+                                                                      boolean 
leaf,
+                                                                      int row,
+                                                                      boolean 
hasFocus) {
+                       setBackgroundNonSelectionColor(Color.WHITE);
+
+                       if(value instanceof DefaultMutableTreeNode) {
+                               Object o = 
((DefaultMutableTreeNode)value).getUserObject();
+
+                               if(o instanceof Index) {
+                                       Index index = (Index)o;
+
+                                       if(index.isUpdating()) {
+                                               
setBackgroundNonSelectionColor(Color.LIGHT_GRAY);
+                                       }
+                               }
+                       }
+                       
+
+                       return super.getTreeCellRendererComponent(tree,
+                                                                 value,
+                                                                 selected,
+                                                                 expanded,
+                                                                 leaf,
+                                                                 row,
+                                                                 hasFocus);
+
+               }
+       }
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java   2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/IndexTreeNode.java   2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,49 @@
+package thaw.plugins.index;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+
+
+public interface IndexTreeNode {
+       
+       public DefaultMutableTreeNode getTreeNode();
+
+       /**
+        * get Id of this node in the database.
+        */
+       public int getId();
+
+       /**
+        * Insert the node in the database.
+        */
+       public boolean create();
+
+       /**
+        * Change the name of the node.
+        */
+       public void rename(String name);
+       
+       /**
+        * Remove the node from the database. (recursive)
+        */
+       public void delete();
+
+       /**
+        * Update from freenet / Update the freenet version. (recursive)
+        */
+       public void update();
+
+       public boolean isUpdating();
+
+       /**
+        * Save the state in the database (recursive).
+        */
+       public void save();
+
+       /**
+        * Get (public) key(s)
+        */
+       public String getKey();
+
+       public void addObserver(java.util.Observer o);
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/Link.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Link.java    2006-08-20 22:58:19 UTC 
(rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Link.java    2006-08-21 03:09:08 UTC 
(rev 10221)
@@ -0,0 +1,17 @@
+package thaw.plugins.index;
+
+import java.sql.*;
+
+import thaw.fcp.*;
+import thaw.plugins.Hsqldb;
+
+public class Link {
+
+       public Link() {
+
+       }
+
+       
+
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java    2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/SearchResult.java    2006-08-21 
03:09:08 UTC (rev 10221)
@@ -0,0 +1,33 @@
+package thaw.plugins.index;
+
+import java.util.Vector;
+
+
+public class SearchResult implements FileList {
+       private Vector fileList = null;
+
+       public SearchResult() {
+
+       }
+
+       public void loadLists(String fileColumnToSort, boolean asc) {
+               fileList = new Vector();
+       }
+
+       public Vector getFileList() {
+               return fileList;
+       }
+
+       public thaw.plugins.index.File getFile(int index) {
+               return null;
+       }
+
+       public Vector getLinkList() {
+               return null;
+       }
+
+       public void unloadLists() {
+               fileList = null;
+       }       
+
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/index/TableCreator.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/TableCreator.java    2006-08-20 
22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/index/TableCreator.java    2006-08-21 
03:09:08 UTC (rev 10221)
@@ -46,6 +46,7 @@
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "name VARCHAR(255) NOT NULL,"
                          + "positionInTree INTEGER NOT NULL,"
+                         + "modifiableIndexes BOOLEAN NOT NULL,"
                          + "parent INTEGER NULL,"
                          + "PRIMARY KEY (id),"
                          + "FOREIGN KEY (parent) REFERENCES indexCategories 
(id))");
@@ -58,45 +59,32 @@
                          + "publicKey VARCHAR(255) NOT NULL,"
                          + "privateKey VARCHAR(255) NULL,"
                          + "positionInTree INTEGER NOT NULL,"
+                         + "revision INTEGER NOT NULL,"
                          + "parent INTEGER NULL,"                        
                          + "PRIMARY KEY (id),"
                          + "FOREIGN KEY (parent) REFERENCES indexCategories 
(id))");

                sendQuery(db,
-                         "CREATE CACHED TABLE fileCategories ("
-                         + "id INTEGER IDENTITY NOT NULL,"
-                         + "name VARCHAR(255) NOT NULL,"
-                         + "positionInTree INTEGER NULL," /* can be null if 
the user doesn't own the index */
-                         + "catParent INTEGER NULL,"
-                         + "indexParent INTEGER NULL,"
-                         + "PRIMARY KEY (id),"
-                         + "FOREIGN KEY (catParent) REFERENCES fileCategories 
(id),"
-                         + "FOREIGN KEY (indexParent) REFERENCES indexes 
(id))");
-
-               sendQuery(db,
                          "CREATE CACHED TABLE files ("
                          + "id INTEGER IDENTITY NOT NULL,"
                          + "publicKey VARCHAR(350) NOT NULL," // key ~= 100 + 
filename == 255 max => 350
+                         + "localPath VARCHAR(500) NULL,"
                          + "mime VARCHAR(50) NULL,"
-                         + "size BIGINT NULL,"
-                         + "catParent INTEGER NULL,"
-                         + "indexParent INTEGER NULL,"
+                         + "size BIGINT NOT NULL,"
+                         + "category VARCHAR(255) NULL,"
+                         + "indexParent INTEGER NOT NULL,"
                          + "PRIMARY KEY (id),"
-                         + "FOREIGN KEY (catParent) REFERENCES fileCategories 
(id),"
                          + "FOREIGN KEY (indexParent) REFERENCES indexes 
(id))");

                sendQuery(db,
                          "CREATE CACHED TABLE links ("
-                         + "id INTEGER IDENTITY NOT NULL,"
-                         + "indexName VARCHAR(255) NOT NULL,"
+                         + "id INTEGER IDENTIFY NOT NULL,"
                          + "publicKey VARCHAR(350) NOT NULL," // key ~= 100 + 
filename == 255 max
                          + "mark INTEGER NOT NULL,"
                          + "comment VARCHAR(512) NOT NULL,"
-                         + "catParent INTEGER NULL,"
-                         + "indexParent INTEGER NULL,"
+                         + "indexParent INTEGER NOT NULL,"
                          + "indexTarget INTEGER NULL,"
                          + "PRIMARY KEY (id),"
-                         + "FOREIGN KEY (catParent) REFERENCES fileCategories 
(id),"
                          + "FOREIGN KEY (indexParent) REFERENCES indexes (id),"
                          + "FOREIGN KEY (indexTarget) REFERENCES indexes 
(id))");

@@ -126,7 +114,6 @@
                sendQuery(db, "DROP TABLE files");
                sendQuery(db, "DROP TABLE links");

-               sendQuery(db, "DROP TABLE fileCategories");
                sendQuery(db, "DROP TABLE indexes");
                sendQuery(db, "DROP TABLE indexCategories");                    
        
        }

Modified: trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java 
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/insertPlugin/DefaultMIMETypes.java 
2006-08-21 03:09:08 UTC (rev 10221)
@@ -25,6 +25,14 @@

        /** Primary extension by MIME type number. */
        private static HashMap primaryExtensionByMimeNumber = new HashMap();
+
+       /**
+        * Just to be able to use thaw.core.Logger.
+        */
+       public DefaultMIMETypes() {
+               
+       }
+

        /**
         * Add a MIME type, without any extensions.
@@ -62,7 +70,7 @@
                                if(mimeTypesByExtension.containsKey(ext)) {
                                        // No big deal
                                        Short s = (Short) 
mimeTypesByExtension.get(ext);
-                                       Logger.info(DefaultMIMETypes.class, 
"Extension "+ext+" assigned to "+byNumber(s.shortValue())+" in preference to 
"+number+":"+type);
+                                       Logger.notice(new DefaultMIMETypes(), 
"Extension "+ext+" assigned to "+byNumber(s.shortValue())+" in preference to 
"+number+":"+type);
                                } else {
                                        // If only one, make it primary
                                        if((outExtension == null) && 
(extensions.length == 1))

Modified: trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueuePanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueuePanel.java       
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueuePanel.java       
2006-08-21 03:09:08 UTC (rev 10221)
@@ -496,25 +496,18 @@
                }
        }

-       public void mouseEntered(MouseEvent e) {
+       public void mouseEntered(MouseEvent e) { }

-       }
+       public void mouseExited(MouseEvent e) { }

-       public void mouseExited(MouseEvent e) {
+       public void mousePressed(MouseEvent e) { }

-       }
+       public void mouseReleased(MouseEvent e) { }

-       public void mousePressed(MouseEvent e) {
-
-       }
-
-       public void mouseReleased(MouseEvent e) {
-
-       }
-
        public void keyPressed(KeyEvent e) { }

        public void keyReleased(KeyEvent e) { refreshDetailPanel(); }
+
        public void keyTyped(KeyEvent e) { }
 }


Modified: trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java  
2006-08-20 22:58:19 UTC (rev 10220)
+++ trunk/apps/Thaw/src/thaw/plugins/queueWatcher/QueueTableModel.java  
2006-08-21 03:09:08 UTC (rev 10221)
@@ -90,7 +90,7 @@
        }


-       private String getPrintableSize(long size) {
+       public static String getPrintableSize(long size) {
                if(size == 0)
                        return I18n.getMessage("thaw.common.unknown");

@@ -271,11 +271,15 @@
        }

        public void notifyObservers(TableModelEvent event) {
+               fireTableChanged(event);
+
+               /*
                TableModelListener[] listeners = getTableModelListeners();

                for(int i = 0 ; i < listeners.length ; i++) {
                        listeners[i].tableChanged(event);
                }
+               */
        }

        public synchronized void update(Observable o, Object arg) {


Reply via email to