version 0.1 v0.1
authorAntoine Jacquet <royale@zerezo.com>
Sat, 5 Apr 2003 22:00:00 +0000 (00:00 +0200)
committerAntoine Jacquet <royale@zerezo.com>
Sat, 5 Apr 2003 22:00:00 +0000 (00:00 +0200)
* initial release

16 files changed:
COPYING [new file with mode: 0644]
README [new file with mode: 0644]
build.bat [new file with mode: 0644]
build.sh [new file with mode: 0755]
build.xml [new file with mode: 0644]
build/splash.jpg [new file with mode: 0644]
src/DonkeyCore.java [new file with mode: 0644]
src/DonkeyGui.java [new file with mode: 0644]
src/DownloadTableModel.java [new file with mode: 0644]
src/Main.java [new file with mode: 0644]
src/RefreshAbstractTableModel.java [new file with mode: 0644]
src/ResultTableModel.java [new file with mode: 0644]
src/ServerTableModel.java [new file with mode: 0644]
src/TableMap.java [new file with mode: 0644]
src/TableSorter.java [new file with mode: 0644]
src/manifest.txt [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..acbaa89
--- /dev/null
+++ b/README
@@ -0,0 +1,9 @@
+jMoule 0.1\r
+site: http://royale.zerezo.com/jmoule/\r
+mail: royale@zerezo.com\r
+\r
+install:\r
+build.bat OR ./build.sh OR ant\r
+\r
+usage:\r
+java -jar dist/jMoule.jar
\ No newline at end of file
diff --git a/build.bat b/build.bat
new file mode 100644 (file)
index 0000000..8dda9b3
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,6 @@
+SET JAVAC=javac\r
+SET JAR=jar\r
+%JAVAC% src/*.java -target 1.3 -d build/\r
+cd build\r
+%JAR% cvfm ../dist/jMoule.jar ../src/manifest.txt .\r
+cd ..
\ No newline at end of file
diff --git a/build.sh b/build.sh
new file mode 100755 (executable)
index 0000000..5dd8ed9
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+JAVAC=javac
+JAR=jar
+$JAVAC src/*.java -target 1.3 -d build/
+cd build
+$JAR cvfm ../dist/jMoule.jar ../src/manifest.txt .
+cd ..
diff --git a/build.xml b/build.xml
new file mode 100644 (file)
index 0000000..6d53508
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,22 @@
+<project name="jMoule" default="dist" basedir=".">\r
+\r
+  <description>jMoule</description>\r
+\r
+  <property name="src" location="src"/>\r
+  <property name="build" location="build"/>\r
+  <property name="dist" location="dist"/>\r
+  <property name="name" location="${dist}/jMoule.jar"/>\r
+  \r
+  <target name="compile" description="compile the source">\r
+    <javac srcdir="${src}" destdir="${build}"/>\r
+  </target>\r
+\r
+  <target name="dist" depends="compile" description="generate the distribution">\r
+    <jar jarfile="${name}" manifest="${src}/manifest.txt" basedir="${build}"/>\r
+  </target>\r
+\r
+  <target name="exec" depends="dist" description="run the project">\r
+    <java jar="${name}" fork="true"/>\r
+  </target>\r
+\r
+</project>
\ No newline at end of file
diff --git a/build/splash.jpg b/build/splash.jpg
new file mode 100644 (file)
index 0000000..fe75caa
Binary files /dev/null and b/build/splash.jpg differ
diff --git a/src/DonkeyCore.java b/src/DonkeyCore.java
new file mode 100644 (file)
index 0000000..023100e
--- /dev/null
@@ -0,0 +1,664 @@
+import java.io.*;\r
+import java.net.*;\r
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import javax.swing.*;\r
+\r
+public class DonkeyCore extends Thread\r
+{\r
+       byte[] buffer=new byte[1024*100];\r
+       int pos;\r
+       int nbsearches=0;\r
+       Socket connection;\r
+       String password;\r
+       Hashtable fileInfos=new Hashtable();\r
+       Hashtable resultInfos=new Hashtable();\r
+       Hashtable serverInfos=new Hashtable();\r
+       Vector searchResults=new Vector();\r
+       //String console=new String();\r
+       JTextArea console=new JTextArea();\r
+       \r
+       public DonkeyCore()\r
+       {\r
+               /*\r
+               Vector fileInfo;\r
+               fileInfo=new Vector();\r
+               fileInfo.add("a");\r
+               fileInfo.add("b");\r
+               fileInfo.add("m");\r
+               fileInfo.add("x");\r
+               fileInfo.add("x");\r
+               fileInfo.add(new Boolean(true));\r
+               fileInfos.put(new Long(0),fileInfo);\r
+               fileInfo=new Vector();\r
+               fileInfo.add("b");\r
+               fileInfo.add("a");\r
+               fileInfo.add("d");\r
+               fileInfo.add("d");\r
+               fileInfo.add("m");\r
+               fileInfo.add(new Boolean(true));\r
+               fileInfos.put(new Long(1),fileInfo);\r
+               fileInfo=new Vector();\r
+               fileInfo.add("g");\r
+               fileInfo.add("a");\r
+               fileInfo.add("k");\r
+               fileInfo.add("k");\r
+               fileInfo.add("i");\r
+               fileInfo.add(new Boolean(true));\r
+               fileInfos.put(new Long(2),fileInfo);\r
+               Vector serverInfo;\r
+               serverInfo=new Vector();\r
+               serverInfo.add("a");\r
+               serverInfo.add("a");\r
+               serverInfo.add("a");\r
+               serverInfo.add(Boolean.FALSE);\r
+               serverInfos.put(new Long(0),serverInfo);\r
+               serverInfo=new Vector();\r
+               serverInfo.add("b");\r
+               serverInfo.add("d");\r
+               serverInfo.add("e");\r
+               serverInfo.add(new Boolean(true));\r
+               serverInfos.put(new Long(1),serverInfo);\r
+               serverInfo=new Vector();\r
+               serverInfo.add("e");\r
+               serverInfo.add("x");\r
+               serverInfo.add("q");\r
+               serverInfo.add(new Boolean(false));\r
+               serverInfos.put(new Long(2),serverInfo);\r
+               serverInfo=new Vector();\r
+               serverInfo.add("a");\r
+               serverInfo.add("b");\r
+               serverInfo.add("n");\r
+               serverInfo.add(new Boolean(true));\r
+               serverInfos.put(new Long(3),serverInfo);\r
+               */\r
+       }\r
+       \r
+       public DonkeyCore(String host,int port,String password)\r
+       {\r
+               this();\r
+               connect(host,port,password);\r
+       }\r
+       \r
+       public boolean connect(String host,int port,String password)\r
+       {\r
+               this.password=password;\r
+               //System.out.println(password);\r
+               try\r
+               {\r
+                       connection=new Socket(host,port);\r
+                       start();\r
+                       return true;\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       e.printStackTrace();\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       public void disconnect()\r
+       {\r
+               try\r
+               {\r
+                       connection.close();\r
+                       connection=null;\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       e.printStackTrace();\r
+               }\r
+       }\r
+       \r
+       public boolean isConnected()\r
+       {\r
+               return connection!=null;\r
+       }\r
+\r
+       void debug(String message)\r
+       {\r
+               //System.out.println(message);\r
+       }\r
+\r
+       boolean readMessage()\r
+       {\r
+               try\r
+               {\r
+                       InputStream i=connection.getInputStream();\r
+                       // read the length of the message\r
+                       long l=i.read()+256*(i.read()+256*(i.read()+256*i.read()));\r
+                       //System.out.print("size: "+l+" ");\r
+                       pos=0;\r
+                       // read the buffer\r
+                       while (pos<l) pos+=i.read(buffer,pos,(int)l-pos);\r
+                       pos=0;\r
+                       // ok\r
+                       \r
+                       // dump\r
+/*\r
+                       if (buffer[0]==3)\r
+                       {\r
+                               System.out.println("Dump: "+new String(buffer,0,(int)l));\r
+                               for (pos=0;pos<l;pos++)\r
+                               {\r
+                                       System.out.print(buffer[pos]+",");\r
+                               }\r
+                       }\r
+                       pos=0;\r
+*/\r
+\r
+                       return true;\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       e.printStackTrace();\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       int readByte()\r
+       {\r
+               byte temp=buffer[pos++];\r
+               return(temp<0?temp+256:temp);\r
+       }\r
+       \r
+       int readInt()\r
+       {\r
+               return(readByte()+256*readByte());\r
+       }\r
+       \r
+       long readLong()\r
+       {\r
+               return(readByte()+256*(readByte()+256*(readByte()+256*readByte())));\r
+       }\r
+       \r
+       String readString()\r
+       {\r
+               int l=readInt();\r
+               if (l>0)\r
+               {\r
+                       String temp=new String(buffer,pos,l);\r
+                       pos+=l;\r
+                       return(temp);\r
+               }\r
+               else return("");\r
+       }\r
+\r
+       synchronized boolean sendMessage(byte[] buffer,int l)\r
+       {\r
+               try\r
+               {\r
+                       connection.getOutputStream().write(l%256);\r
+                       connection.getOutputStream().write(l/256);\r
+                       connection.getOutputStream().write(0);\r
+                       connection.getOutputStream().write(0);\r
+                       connection.getOutputStream().write(buffer,0,l);\r
+                       return true;\r
+               }\r
+               catch (Exception e)\r
+               {\r
+                       e.printStackTrace();\r
+                       return false;\r
+               }\r
+       }\r
+       \r
+       public void connectMore()\r
+       {\r
+       byte[] buffer=new byte[2];\r
+    buffer[0]=1; buffer[1]=0; // function\r
+    sendMessage(buffer,2);\r
+       }\r
+\r
+       public void cleanOld()\r
+       {\r
+       byte[] buffer=new byte[2];\r
+    buffer[0]=2; buffer[1]=0; // function\r
+    sendMessage(buffer,2);\r
+       }\r
+\r
+       public void kill()\r
+       {\r
+       byte[] buffer=new byte[2];\r
+    buffer[0]=3; buffer[1]=0; // function\r
+    sendMessage(buffer,2);\r
+       }\r
+\r
+       public void extend()\r
+       {\r
+       byte[] buffer=new byte[2];\r
+    buffer[0]=4; buffer[1]=0; // function\r
+    sendMessage(buffer,2);\r
+       }\r
+       \r
+       public void download(Long fileID)\r
+       {\r
+               byte[] buffer=new byte[9];\r
+               int i=0;\r
+    buffer[i++]=50; buffer[i++]=0; // function\r
+    buffer[i++]=0; buffer[i++]=0; // result_names (empty list)\r
+    long id=fileID.longValue();\r
+    for (int j=0;j<4;j++)\r
+    {\r
+       buffer[i++]=(byte)(id%256);\r
+       id/=256;\r
+    }\r
+    buffer[i++]=0; // force\r
+       sendMessage(buffer,i);\r
+       }\r
+       \r
+       public void switchDownload(Long fileID,boolean bool)\r
+       {\r
+               byte[] buffer=new byte[9];\r
+               int i=0;\r
+    buffer[i++]=23; buffer[i++]=0; // function\r
+    long id=fileID.longValue();\r
+    for (int j=0;j<4;j++)\r
+    {\r
+       buffer[i++]=(byte)(id%256);\r
+       id/=256;\r
+    }\r
+    if (bool)\r
+       buffer[i++]=1;\r
+    else\r
+       buffer[i++]=0;\r
+       sendMessage(buffer,i);\r
+       }\r
+       \r
+       public void connectServer(Long serverID)\r
+       {\r
+               byte[] buffer=new byte[6];\r
+               int i=0;\r
+    buffer[i++]=21; buffer[i++]=0; // function\r
+    long id=serverID.longValue();\r
+    for (int j=0;j<4;j++)\r
+    {\r
+       buffer[i++]=(byte)(id%256);\r
+       id/=256;\r
+    }\r
+       sendMessage(buffer,i);\r
+       }\r
+       \r
+       public void disconnectServer(Long serverID)\r
+       {\r
+               byte[] buffer=new byte[6];\r
+               int i=0;\r
+    buffer[i++]=22; buffer[i++]=0; // function\r
+    long id=serverID.longValue();\r
+    for (int j=0;j<4;j++)\r
+    {\r
+       buffer[i++]=(byte)(id%256);\r
+       id/=256;\r
+    }\r
+       sendMessage(buffer,i);\r
+       }\r
+       \r
+       public Vector search(String query)\r
+       {\r
+       byte[] buffer=new byte[1024*100];\r
+       int i=0,j;\r
+    buffer[i++]=42; buffer[i++]=0; // function\r
+    buffer[i++]=(byte)(nbsearches%256); buffer[i++]=(byte)(nbsearches/256); \r
+    buffer[i++]=0; buffer[i++]=0; // num\r
+    buffer[i++]=4; // keywords\r
+    buffer[i++]=0; buffer[i++]=0; // empty string\r
+    buffer[i++]=(byte)(query.length()%256);\r
+    buffer[i++]=(byte)(query.length()/256);\r
+    for (j=0;j<query.length();j++)\r
+       buffer[i++]=(byte)query.charAt(j);\r
+    buffer[i++]=50; buffer[i++]=0; buffer[i++]=0; buffer[i++]=0; // max hits\r
+    buffer[i++]=1; // type\r
+    Vector searchResult=new Vector();\r
+    searchResults.add(searchResult);\r
+    sendMessage(buffer,i);\r
+    nbsearches++;\r
+    /*\r
+    Vector resultInfo=new Vector();\r
+    resultInfo.add(new Long(1));\r
+    resultInfo.add("a");\r
+    resultInfo.add("a");\r
+    resultInfo.add("a");\r
+    resultInfo.add(new Boolean(false));\r
+    searchResult.add(resultInfo);\r
+    resultInfo=new Vector();\r
+    resultInfo.add(new Long(2));\r
+    resultInfo.add("b");\r
+    resultInfo.add("b");\r
+    resultInfo.add("b");\r
+    resultInfo.add(new Boolean(false));\r
+    searchResult.add(resultInfo);\r
+    resultInfo=new Vector();\r
+    resultInfo.add(new Long(3));\r
+    resultInfo.add("c");\r
+    resultInfo.add("c");\r
+    resultInfo.add("c");\r
+    resultInfo.add(new Boolean(false));\r
+    searchResult.add(resultInfo);\r
+    */\r
+    return searchResult;\r
+       }\r
+       \r
+       public void run()\r
+       {\r
+               while(readMessage())\r
+               {\r
+                       //String serverStates[]={"NotConnected -1","Connecting","Connected_initiating","Connected_downloading","Connected -1","Connected n","NewHost","RemovedHost","BlackListedHost","NotConnected n"};\r
+                       Boolean serverStates[]={\r
+                               Boolean.FALSE, // "NotConnected -1"\r
+                               Boolean.FALSE, // "Connecting"\r
+                               Boolean.TRUE,  // "Connected_initiating"\r
+                               Boolean.TRUE,  // "Connected_downloading"\r
+                               Boolean.TRUE,  // "Connected -1"\r
+                               Boolean.TRUE,  // "Connected n"\r
+                               Boolean.FALSE, // "NewHost"\r
+                               Boolean.FALSE, // "RemovedHost"\r
+                               Boolean.FALSE, // "BlackListedHost"\r
+                               Boolean.FALSE  // "NotConnected n"\r
+                       };\r
+                       Boolean fileStates[]={\r
+                               Boolean.TRUE,  // FileDownloading\r
+                               Boolean.FALSE, // FilePaused\r
+                       Boolean.TRUE,  // FileDownloaded\r
+                       Boolean.FALSE, // FileShared\r
+                       Boolean.FALSE, // FileCancelled\r
+                       Boolean.FALSE, // FileNew\r
+                       Boolean.FALSE, // FileAborted s\r
+                               Boolean.FALSE  // FileQueued\r
+                       };\r
+                       int i,n,f;\r
+                       Long id;\r
+                       String tags;\r
+                       switch(f=readInt()) // fonction\r
+                       {\r
+                               \r
+                               // CoreProtocol\r
+                               case 0:\r
+                                       debug("CoreProtocol: "+readLong());\r
+                                       // (06:00:00:00:) 00:00:10:00:00:00 GuiProtocol\r
+                                       for (i=0;i<6;i++) buffer[i]=0;\r
+                                       buffer[2]=10;\r
+                                       sendMessage(buffer,6);\r
+                                       // (04:00:00:00:) 05:00:00:00 Password (empty)\r
+                                       i=0;\r
+                                       buffer[i++]=5; buffer[i++]=0; // function\r
+                                       buffer[i++]=(byte)(password.length()%256);\r
+                                       buffer[i++]=(byte)(password.length()/256);\r
+                                       for (int j=0;j<password.length();j++)\r
+                                               buffer[i++]=(byte)password.charAt(j);\r
+                                       sendMessage(buffer,i);\r
+                                       break;\r
+\r
+                               // Options_info\r
+                               case 1:\r
+                                       debug("Options_info:");\r
+                                       n=readInt();\r
+                                       for (i=0;i<n;i++)\r
+                                               debug(readString()+" = "+readString());\r
+                                       break;\r
+                                       \r
+                               // DefineSearches\r
+                               case 3:\r
+                                       n=readInt();\r
+                                       debug("DefineSearches: "+n);\r
+                                       /*for (i=0;i<n;i++)\r
+                                       {\r
+                                               System.out.println(readString()); // name\r
+                                               System.out.println(readByte());\r
+                                       }*/\r
+                                       break;\r
+                                       \r
+                               // Result_info\r
+                               case 4:\r
+                                       Vector resultInfo=new Vector();\r
+                                       debug("Result_info: ");\r
+                                       id=new Long(readLong());\r
+                                       resultInfo.add(id);\r
+                                       readLong(); // network\r
+                                       n=readInt();\r
+                                       resultInfo.add(readString());\r
+                                       for (i=0;i<n-1;i++) readString(); // names\r
+                                       for (i=0;i<16;i++) readByte(); // hash\r
+                                       resultInfo.add(new Long(readLong())); // Size\r
+                                       readString(); // Format\r
+                                       readString(); // Type\r
+                                       tags=new String();\r
+                                       n=readInt();\r
+                                       for (i=0;i<n;i++)\r
+                                       {\r
+                                               readString(); // TagName\r
+                                               switch (readByte()) // TagValue\r
+                                               {\r
+                                                       case 0:\r
+                                                       case 1:\r
+                                                               tags=tags.concat(""+readLong()+" ");\r
+                                                               break;\r
+                                                       case 2:\r
+                                                               tags=tags.concat(readString()+" ");\r
+                                                               break;\r
+                                                       case 3:\r
+                                                               tags=tags.concat(""+readByte()+"."+readByte()+"."+readByte()+"."+readByte()+" ");\r
+                                                               break;\r
+                                               }\r
+                                       }\r
+                                       resultInfo.add(tags);\r
+                                       readString(); // Comment\r
+                                       readByte(); // Done (boolean)\r
+                                       resultInfo.add(new Boolean(false)); // download ?\r
+                                       resultInfos.put(id,resultInfo);\r
+                                       break;\r
+\r
+                               // Search_result                                        \r
+                               case 5:\r
+                                       int search=(int)readLong(); // Search\r
+                                       Long info=new Long(readLong()); // Result_Info\r
+                                       ((Vector)searchResults.get(search)).add(resultInfos.get(info));\r
+                                       break;\r
+                               \r
+                               // File_info\r
+                               case 7:\r
+                               case 40:\r
+                               case 43: \r
+                                       Vector fileInfo=new Vector();\r
+                                       debug("FileInformation: ");\r
+                                       id=new Long(readLong()); // id\r
+                                       readLong(); // network\r
+                                       n=readInt();\r
+                                       readString();\r
+                                       fileInfo.add(readString());\r
+                                       for (i=0;i<n-2;i++)     debug(readString()); // names\r
+                                       //for (i=0;i<n;i++)     debug(readString()); // names\r
+                                       for (i=0;i<16;i++) readByte(); // hash\r
+                                       //readLong(); // size\r
+                                       //readLong(); // downloaded\r
+                                       long filesize=readLong();\r
+                                       long filedl=readLong();\r
+                                       fileInfo.add(new Long(filesize));\r
+                                       fileInfo.add(new Long(filedl));\r
+                                       fileInfo.add(new Float(Math.round(10000*filedl/filesize)/100.0));\r
+                                       //debug(readLong()+"/"+readLong());\r
+                                       readLong(); // nlocations\r
+                                       readLong(); // nclients\r
+                                       int state=readByte(); // file_state\r
+                                       readString(); // chunks\r
+                                       readString(); // availability\r
+                                       //fileInfo.add(new Float(readString())); // rate\r
+                                       fileInfo.add(new Float(Math.round(Float.parseFloat(readString()))/1000.0));\r
+                                       n=readInt();\r
+                                       for (i=0;i<n;i++) readString(); // chunks age\r
+                                       readString(); // age\r
+                                       switch (readByte()) // format\r
+                                       {\r
+                                               case 0:\r
+                                                       debug("Unknown_format");\r
+                                                       break;\r
+                                               case 1: // FormatType\r
+                                                       //readString(); readString();\r
+                                                       debug("FormatType: "+readString()+" "+readString());\r
+                                                       break;\r
+                                               case 2: // AVI\r
+                                                       debug("AVI: ");\r
+                                                       debug("codec: "+readString()); // codec\r
+                                                       debug(readLong()+"x"+readLong()+", "+readLong()+" fps "+readLong()+" rate")     ;\r
+                                                       break;\r
+                                               case 3: // MP3\r
+                                                       debug("MP3: ");\r
+                                                       debug("title: "+readString()); // title\r
+                                                       debug("artist: "+readString()); // artist\r
+                                                       debug("album: "+readString()); // album\r
+                                                       debug("year: "+readString()); // year\r
+                                                       debug("comment: "+readString()); // comment\r
+                                                       debug("track: "+readLong()); // track number\r
+                                                       debug("genre: "+readLong()); // genre\r
+                                                       break;\r
+                                       }\r
+                                       fileInfo.add(fileStates[state]);\r
+                                       fileInfos.put(id,fileInfo);\r
+                                       break;\r
+                               \r
+                               // File_source\r
+                               case 10:\r
+                                       // file_num f, client_num c\r
+                                       //debug("File_source: "+readInt()+" "+readInt());\r
+                                       break;\r
+                               \r
+                               // Server_state\r
+                               case 13:\r
+                                       //debug("Server_state: "+readLong()+" etat: "+readByte());\r
+                                       id=new Long(readLong());\r
+                                       ((Vector)serverInfos.get(id)).setElementAt(serverStates[readByte()],3); // server_state\r
+                                       //System.out.println(id+" : state changed");\r
+                                       break;\r
+                                       \r
+                               // Client_state\r
+                               case 16:\r
+                                       debug("Client_state: "+readLong()+" etat: "+readByte());\r
+                                       break;\r
+                               \r
+                               // Client_info\r
+                               case 15:\r
+                                       /*\r
+                                       debug("Client_info: ");\r
+                                       debug("num: "+readLong());\r
+                                       debug("network: "+readLong());\r
+                                       switch(readByte())\r
+                                       {\r
+                                               case 0:\r
+                                                       // Known_location\r
+                                                       debug("type: Known_location");\r
+                                                       debug("ip: "+readByte()+"."+readByte()+"."+readByte()+"."+readByte());\r
+                                                       debug("port: "+readInt());\r
+                                                       break;\r
+                                               case 1:\r
+                                                       // Indirect_location\r
+                                                       debug("type: Indirect_location");\r
+                                                       debug("name: "+readString());\r
+                                                       break;\r
+                                       }\r
+                                       */\r
+                                       break;\r
+                               \r
+                               // Console\r
+                               case 19: \r
+                                       debug("Console: ");\r
+                                       //console=console.concat(readString());\r
+                                       console.append(readString());\r
+                                       break;\r
+                               \r
+                               // Network_info\r
+                               case 20:\r
+                                       n=readInt();\r
+                                       debug("Network_info: "+readString());\r
+                                       break;\r
+                                       \r
+                               // Server_info\r
+                               case 26:\r
+                                       Vector serverInfo=new Vector();\r
+                                       debug("Server_info: ");\r
+                                       id=new Long(readLong()); // id\r
+                                       readLong(); // network\r
+                                       // only works if proto>=2\r
+                                       String host=null;\r
+                                       switch(readByte())\r
+                                       {\r
+                                               case 0:\r
+                                                       //debug("ip: "+readByte()+"."+readByte()+"."+readByte()+"."+readByte());\r
+                                                       host=""+readByte()+"."+readByte()+"."+readByte()+"."+readByte();\r
+                                                       break;\r
+                                               case 1:\r
+                                                       //debug("name: "+readString());\r
+                                                       host=readString();\r
+                                                       break;\r
+                                       }\r
+                                       //debug("port: "+readInt());\r
+                                       host=host+":"+readInt(); // port\r
+                                       serverInfo.add(host);\r
+                                       readLong(); // score\r
+                                       tags=new String();\r
+                                       n=readInt();\r
+                                       for (i=0;i<n;i++)\r
+                                       {\r
+                                               readString(); // TagName\r
+                                               switch (readByte()) // TagValue\r
+                                               {\r
+                                                       case 0:\r
+                                                       case 1:\r
+                                                               tags=tags.concat(""+readLong()+" ");\r
+                                                               break;\r
+                                                       case 2:\r
+                                                               tags=tags.concat(readString()+" ");\r
+                                                               break;\r
+                                                       case 3:\r
+                                                               tags=tags.concat(""+readByte()+"."+readByte()+"."+readByte()+"."+readByte()+" ");\r
+                                                               break;\r
+                                               }\r
+                                       }\r
+                                       serverInfo.add(new Long(readLong())); // nusers\r
+                                       serverInfo.add(new Long(readLong())); // nfiles\r
+                                       serverInfo.add(serverStates[readByte()]); // server_state\r
+                                       serverInfos.put(id,serverInfo);\r
+                                       break;\r
+                                                               \r
+                               // Add_section_option\r
+                               case 36:\r
+                                       debug("Add_section_option: "+readString()+" "+readString()+" "+readString());\r
+                                       break;\r
+                               \r
+                               // Add_plugin_option\r
+                               case 38:\r
+                                       debug("Add_plugin_option: "+readString()+" "+readString()+" "+readString());\r
+                                       break;\r
+                                       \r
+                               // File_downloaded\r
+                               case 46:\r
+                                       debug("File_downloaded: ");\r
+                                       debug("n: "+readLong());\r
+                                       debug("size: "+readLong());\r
+                                       debug("rate: "+readString());\r
+                                       debug("last_seen: "+readLong());\r
+                                       break;\r
+                                       \r
+                               // Shared_file_info\r
+                               case 48:\r
+                                       debug("Shared_file_info: ");\r
+                                       debug("num: "+readLong());\r
+                                       debug("network: "+readLong());\r
+                                       debug("name: "+readString());\r
+                                       debug("size: "+readLong());\r
+                                       // ...                                  \r
+                                       break;\r
+                                       \r
+                               // Client_stats\r
+                               case 49:\r
+                                       debug("Client_stats: ");\r
+                                       // stats...\r
+                                       break;\r
+\r
+                               default:\r
+                                       debug("Fonction: "+f);\r
+                                       break;\r
+                                       \r
+                       }\r
+                       //System.out.println();\r
+               }\r
+       }\r
+       \r
+}
\ No newline at end of file
diff --git a/src/DonkeyGui.java b/src/DonkeyGui.java
new file mode 100644 (file)
index 0000000..0cbf25a
--- /dev/null
@@ -0,0 +1,229 @@
+import java.awt.*;\r
+import java.awt.event.*;\r
+import javax.swing.*;\r
+import javax.swing.table.*;\r
+import java.util.Vector;\r
+\r
+public class DonkeyGui extends JFrame\r
+{\r
+\r
+       DonkeyGui(final DonkeyCore donkeyCore)\r
+       {\r
+               Dimension screensize=Toolkit.getDefaultToolkit().getScreenSize();\r
+               \r
+               // Splash window\r
+               JWindow splash=new JWindow();\r
+               splash.getContentPane().add(new JLabel(new ImageIcon(getClass().getResource("/splash.jpg"))));\r
+               splash.pack();\r
+               Dimension windowsize=splash.getSize();\r
+    splash.setLocation((screensize.width-windowsize.width)/2,(screensize.height-windowsize.height)/2);\r
+         splash.setVisible(true);\r
+               \r
+               // Main window\r
+               setTitle("jMoule");\r
+               setSize(600,400);\r
+    windowsize=getSize();\r
+    setLocation((screensize.width-windowsize.width)/2,(screensize.height-windowsize.height)/2);\r
+               addWindowListener(new WindowAdapter() {\r
+      public void windowClosing(WindowEvent e)\r
+      {\r
+        System.exit(0);\r
+      }\r
+    });\r
+    \r
+    JTabbedPane tabbedPane=new JTabbedPane();\r
+               getContentPane().add(tabbedPane);\r
+\r
+               // Control panel\r
+               JPanel controlPanel=new JPanel();\r
+               JPanel connectPanel=new JPanel();\r
+               connectPanel.add(new JLabel("Host : "));\r
+               final JTextField hostText=new JTextField("",10);\r
+    connectPanel.add(hostText);\r
+               connectPanel.add(new JLabel("Password : "));\r
+               final JPasswordField passwordText=new JPasswordField("",5);\r
+    connectPanel.add(passwordText);\r
+    JButton connectButton=new JButton("Connect");\r
+               connectPanel.add(connectButton);\r
+    JButton killButton=new JButton("Kill");\r
+               connectPanel.add(killButton);\r
+    connectButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("connectButton");\r
+                   if (hostText.getText().length()==0) return;\r
+                   donkeyCore.connect(hostText.getText(),4001,new String(passwordText.getPassword()));\r
+      }\r
+    });\r
+    killButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("killButton");\r
+                   donkeyCore.kill();\r
+      }\r
+    });\r
+               tabbedPane.add(connectPanel,"Control");\r
+\r
+               // Server panel\r
+               JPanel serverPanel=new JPanel(new BorderLayout());\r
+               JPanel servertopPanel=new JPanel();\r
+               JButton connectMoreButton=new JButton("Connect More");\r
+               servertopPanel.add(connectMoreButton);\r
+               JButton cleanOldButton=new JButton("Clean Old Servers");\r
+               servertopPanel.add(cleanOldButton);\r
+               /*\r
+               JButton sconnectButton=new JButton("Connect");\r
+               servertopPanel.add(sconnectButton);\r
+               JButton disconnectButton=new JButton("Disconnect");\r
+               servertopPanel.add(disconnectButton);\r
+               */\r
+               serverPanel.add(servertopPanel,"North");\r
+               //final JTable serverTable=new JTable(new ServerTableModel(donkeyCore.serverInfos));\r
+\r
+        TableModel dataModel=new ServerTableModel(donkeyCore.serverInfos,donkeyCore);\r
+        TableSorter sorter=new TableSorter(dataModel);\r
+        JTable tableView=new JTable(sorter);\r
+        tableView.setColumnSelectionAllowed(false);\r
+        tableView.setRowSelectionAllowed(false);\r
+        sorter.addMouseListenerToHeaderInTable(tableView);\r
+\r
+               //serverPanel.add(new JScrollPane(serverTable),"Center");\r
+               serverPanel.add(new JScrollPane(tableView),"Center");\r
+               tabbedPane.add(serverPanel,"Servers");\r
+    connectMoreButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("connectMoreButton");\r
+                   donkeyCore.connectMore();\r
+      }\r
+    });\r
+    cleanOldButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("cleanOldButton");\r
+                   donkeyCore.cleanOld();\r
+      }\r
+    });\r
+               /*\r
+    sconnectButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   System.out.println("sconnectButton");\r
+                   for (int i=0;i<serverTable.getSelectedRowCount();i++)\r
+                   {\r
+                       ServerTableModel m=(ServerTableModel)serverTable.getModel();\r
+                       //Vector v=(Vector)r.serverInfos.get(serverTable.getSelectedRows()[i]);\r
+                           donkeyCore.connectServer((Long)m.getValueAt(i,0));\r
+                   }\r
+      }\r
+    });\r
+    disconnectButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   System.out.println("disconnectButton");\r
+                   for (int i=0;i<serverTable.getSelectedRowCount();i++)\r
+                   {\r
+                       ServerTableModel m=(ServerTableModel)serverTable.getModel();\r
+                       //Vector v=(Vector)r.serverInfos.get(serverTable.getSelectedRows()[i]);\r
+                           donkeyCore.disconnectServer((Long)m.getValueAt(i,0));\r
+                   }\r
+      }\r
+    });\r
+    */\r
+\r
+               // Search panel\r
+               JPanel searchPanel=new JPanel(new BorderLayout());\r
+    JPanel topPanel=new JPanel();\r
+    topPanel.add(new JLabel("Query : "));\r
+    final JTextField searchText=new JTextField("",15);\r
+    topPanel.add(searchText);\r
+    JButton searchButton=new JButton("Search");\r
+    topPanel.add(searchButton);\r
+    JButton extendButton=new JButton("Extend");\r
+    topPanel.add(extendButton);\r
+    /*\r
+    JButton downloadButton=new JButton("Download");\r
+    topPanel.add(downloadButton);\r
+    */\r
+    searchPanel.add(topPanel,"North");\r
+               final JTabbedPane resultsPane=new JTabbedPane();        \r
+               searchPanel.add(resultsPane,"Center");\r
+               final Vector resultTables=new Vector();\r
+    searchButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("searchButton");\r
+                   if (searchText.getText().length()==0) return;\r
+        Vector searchResult=donkeyCore.search(searchText.getText());\r
+        \r
+        /*\r
+        JTable resultTable=new JTable(new ResultTableModel(searchResult));\r
+        resultTables.add(resultTable);\r
+        resultsPane.add(new JScrollPane(resultTable),searchText.getText());\r
+        resultsPane.setSelectedIndex(resultsPane.getTabCount()-1);\r
+        */\r
+        \r
+        ResultTableModel resultModel=new ResultTableModel(searchResult,donkeyCore);\r
+        TableSorter sorter=new TableSorter(resultModel);\r
+        JTable tableView=new JTable(sorter);\r
+        tableView.setColumnSelectionAllowed(false);\r
+        tableView.setRowSelectionAllowed(false);\r
+        resultTables.add(tableView);\r
+        sorter.addMouseListenerToHeaderInTable(tableView);\r
+        resultsPane.add(new JScrollPane(tableView),searchText.getText());\r
+        resultsPane.setSelectedIndex(resultsPane.getTabCount()-1);\r
+\r
+      }\r
+    });\r
+    extendButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   //System.out.println("extendButton");\r
+                   donkeyCore.extend();\r
+      }\r
+    });\r
+    /*\r
+    downloadButton.addActionListener(new ActionListener() {\r
+      public void actionPerformed(ActionEvent event)\r
+      {\r
+                   System.out.println("downloadButton");\r
+                   JTable resultTable=(JTable)resultTables.get(resultsPane.getSelectedIndex());\r
+                   for (int i=0;i<resultTable.getSelectedRowCount();i++)\r
+                   {\r
+                       ResultTableModel r=(ResultTableModel)resultTable.getModel();\r
+                       Vector v=(Vector)r.searchResult.get(resultTable.getSelectedRows()[i]);\r
+                       donkeyCore.download((Long)v.get(0));\r
+                   }\r
+      }\r
+    });\r
+    */\r
+               tabbedPane.add(searchPanel,"Search");\r
+\r
+               // Downloads panel\r
+    //tabbedPane.add(new JScrollPane(new JTable(new DownloadTableModel(donkeyCore.fileInfos))),"Downloads");\r
+        //DownloadTableModel \r
+        dataModel=new DownloadTableModel(donkeyCore.fileInfos,donkeyCore);\r
+        //TableSorter \r
+        sorter=new TableSorter(dataModel);\r
+        //JTable \r
+        tableView=new JTable(sorter);\r
+        tableView.setColumnSelectionAllowed(false);\r
+        tableView.setRowSelectionAllowed(false);\r
+        sorter.addMouseListenerToHeaderInTable(tableView);\r
+        tabbedPane.add(new JScrollPane(tableView),"Downloads");\r
+\r
+    // Console panel\r
+    tabbedPane.add(new JScrollPane(donkeyCore.console),"Console");\r
+\r
+               try\r
+               {\r
+                       Thread.sleep(2000);\r
+               }\r
+               catch (Exception e)\r
+               {}\r
+               splash.setVisible(false);\r
+               show();\r
+               \r
+       }\r
+       \r
+}\r
diff --git a/src/DownloadTableModel.java b/src/DownloadTableModel.java
new file mode 100644 (file)
index 0000000..0fe53c6
--- /dev/null
@@ -0,0 +1,51 @@
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import javax.swing.table.*;\r
+\r
+public class DownloadTableModel extends RefreshAbstractTableModel\r
+{\r
+\r
+       Hashtable fileInfos;\r
+       String columns[]={"Number","File Name","Size","Downloaded","%","Rate","Running"};\r
+       DonkeyCore donkeyCore;\r
+       \r
+       public DownloadTableModel(Hashtable fileInfos,DonkeyCore donkeyCore)\r
+       {\r
+               this.donkeyCore=donkeyCore;\r
+               this.fileInfos=fileInfos;\r
+       }\r
+       \r
+       public int getColumnCount()\r
+       {\r
+               return columns.length;\r
+       }\r
+       \r
+       public String getColumnName(int col)\r
+       {\r
+               return columns[col];\r
+       }\r
+\r
+       public int getRowCount()\r
+       {\r
+               return fileInfos.size();\r
+       }\r
+       \r
+       public Object getValueAt(int row,int col)\r
+       {\r
+               if (col==0) return fileInfos.keySet().toArray()[row];\r
+               return ((Vector)fileInfos.values().toArray()[row]).get(col-1);\r
+       }\r
+\r
+       public boolean isCellEditable(int row,int col)\r
+       {\r
+               return col==columns.length-1;\r
+       }\r
+       \r
+       public void setValueAt(Object o,int row,int col)\r
+       {\r
+               Long id=(Long)getValueAt(row,0);\r
+               Vector fileInfo=(Vector)fileInfos.get(id);\r
+               donkeyCore.switchDownload((Long)getValueAt(row,0),((Boolean)o).booleanValue());\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/src/Main.java b/src/Main.java
new file mode 100644 (file)
index 0000000..d8dce60
--- /dev/null
@@ -0,0 +1,9 @@
+public class Main\r
+{\r
+       \r
+       public static void main(String[] args) throws Exception\r
+       {\r
+               new DonkeyGui(new DonkeyCore());                \r
+       }\r
+       \r
+}
\ No newline at end of file
diff --git a/src/RefreshAbstractTableModel.java b/src/RefreshAbstractTableModel.java
new file mode 100644 (file)
index 0000000..61f2ee2
--- /dev/null
@@ -0,0 +1,44 @@
+import javax.swing.table.*;\r
+\r
+public abstract class RefreshAbstractTableModel extends AbstractTableModel\r
+{\r
+\r
+       public RefreshAbstractTableModel()\r
+       {\r
+               Thread refreshThread=new Thread()\r
+               {\r
+                       public void run()\r
+                       {\r
+                               //int oldRowCount=0,newRowCount;\r
+                               try\r
+                               {\r
+                                       for (;;)\r
+                                       {\r
+                                               sleep(5000);\r
+                                               /*\r
+                                               newRowCount=getRowCount();\r
+                                               if (oldRowCount<newRowCount)\r
+                                                       fireTableRowsInserted(oldRowCount-1,newRowCount-1);\r
+                                               if (oldRowCount>newRowCount)\r
+                                                       fireTableRowsDeleted(newRowCount-1,oldRowCount-1);\r
+                                               fireTableRowsUpdated(0,newRowCount-1);\r
+                                               oldRowCount=newRowCount;\r
+                                               */\r
+                                               fireTableDataChanged();\r
+                                       }\r
+                               }\r
+                               catch(Exception e)\r
+                               {\r
+                                       e.printStackTrace();\r
+                               }\r
+                       }\r
+               };\r
+               refreshThread.start();\r
+       }\r
+       \r
+  public Class getColumnClass(int col)\r
+  {\r
+       return getValueAt(0,col).getClass();\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ResultTableModel.java b/src/ResultTableModel.java
new file mode 100644 (file)
index 0000000..709eb8c
--- /dev/null
@@ -0,0 +1,49 @@
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import javax.swing.table.*;\r
+\r
+public class ResultTableModel extends RefreshAbstractTableModel\r
+{\r
+\r
+       Vector searchResult;\r
+       String columns[]={"Number","File Name","Size","Tags","Download"};\r
+       DonkeyCore donkeyCore;\r
+       \r
+       public ResultTableModel(Vector searchResult,DonkeyCore donkeyCore)\r
+       {\r
+               this.donkeyCore=donkeyCore;\r
+               this.searchResult=searchResult;\r
+       }\r
+       \r
+       public int getColumnCount()\r
+       {\r
+               return columns.length;\r
+       }\r
+       \r
+       public String getColumnName(int col)\r
+       {\r
+               return columns[col];\r
+       }\r
+\r
+       public int getRowCount()\r
+       {\r
+               return searchResult.size();\r
+       }\r
+       \r
+       public Object getValueAt(int row,int col)\r
+       {\r
+               return ((Vector)searchResult.get(row)).get(col);\r
+       }\r
+       \r
+       public boolean isCellEditable(int row,int col)\r
+       {\r
+               return col==columns.length-1;\r
+       }\r
+       \r
+       public void setValueAt(Object o,int row,int col)\r
+       {\r
+               ((Vector)searchResult.get(row)).setElementAt(new Boolean(true),col);\r
+               donkeyCore.download((Long)getValueAt(row,0));\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/src/ServerTableModel.java b/src/ServerTableModel.java
new file mode 100644 (file)
index 0000000..ac7539c
--- /dev/null
@@ -0,0 +1,59 @@
+import java.util.Hashtable;\r
+import java.util.Vector;\r
+import javax.swing.table.*;\r
+\r
+public class ServerTableModel extends RefreshAbstractTableModel\r
+{\r
+\r
+       Hashtable serverInfos;\r
+       String columns[]={"Number","Host","Users","Files","Connected"};\r
+       DonkeyCore donkeyCore;\r
+       \r
+       public ServerTableModel(Hashtable serverInfos,DonkeyCore donkeyCore)\r
+       {\r
+               this.donkeyCore=donkeyCore;\r
+               this.serverInfos=serverInfos;\r
+       }\r
+       \r
+       public int getColumnCount()\r
+       {\r
+               return columns.length;\r
+       }\r
+       \r
+       public String getColumnName(int col)\r
+       {\r
+               return columns[col];\r
+       }\r
+\r
+       public int getRowCount()\r
+       {\r
+               return serverInfos.size();\r
+       }\r
+       \r
+       public Object getValueAt(int row,int col)\r
+       {\r
+               if (col==0) return serverInfos.keySet().toArray()[row];\r
+               return ((Vector)serverInfos.values().toArray()[row]).get(col-1);\r
+       }\r
+\r
+       public boolean isCellEditable(int row,int col)\r
+       {\r
+               return col==columns.length-1;\r
+       }\r
+       \r
+       public void setValueAt(Object o,int row,int col)\r
+       {\r
+               Long id=(Long)getValueAt(row,0);\r
+               Vector serverInfo=(Vector)serverInfos.get(id);\r
+               if (((Boolean)serverInfo.elementAt(3)).booleanValue())\r
+               {\r
+                       //((Vector)searchResult.get(row)).setElementAt(new Boolean(true),col);\r
+                       donkeyCore.disconnectServer((Long)getValueAt(row,0));\r
+               }\r
+               else\r
+               {\r
+                       donkeyCore.connectServer((Long)getValueAt(row,0));\r
+               }\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/src/TableMap.java b/src/TableMap.java
new file mode 100644 (file)
index 0000000..c010ddc
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/** 
+ * In a chain of data manipulators some behaviour is common. TableMap
+ * provides most of this behavour and can be subclassed by filters
+ * that only need to override a handful of specific methods. TableMap 
+ * implements TableModel by routing all requests to its model, and
+ * TableModelListener by routing all events to its listeners. Inserting 
+ * a TableMap which has not been subclassed into a chain of table filters 
+ * should have no effect.
+ *
+ * @version 1.8 02/06/02
+ * @author Philip Milne */
+
+import javax.swing.table.*; 
+import javax.swing.event.TableModelListener; 
+import javax.swing.event.TableModelEvent; 
+
+public class TableMap extends AbstractTableModel implements TableModelListener
+{
+    protected TableModel model; 
+
+    public TableModel  getModel() {
+        return model;
+    }
+
+    public void  setModel(TableModel model) {
+        this.model = model; 
+        model.addTableModelListener(this); 
+    }
+
+    // By default, Implement TableModel by forwarding all messages 
+    // to the model. 
+
+    public Object getValueAt(int aRow, int aColumn) {
+        return model.getValueAt(aRow, aColumn); 
+    }
+       
+    public void setValueAt(Object aValue, int aRow, int aColumn) {
+        model.setValueAt(aValue, aRow, aColumn); 
+    }
+
+    public int getRowCount() {
+        return (model == null) ? 0 : model.getRowCount(); 
+    }
+
+    public int getColumnCount() {
+        return (model == null) ? 0 : model.getColumnCount(); 
+    }
+       
+    public String getColumnName(int aColumn) {
+        return model.getColumnName(aColumn); 
+    }
+
+    public Class getColumnClass(int aColumn) {
+        return model.getColumnClass(aColumn); 
+    }
+       
+    public boolean isCellEditable(int row, int column) { 
+         return model.isCellEditable(row, column); 
+    }
+//
+// Implementation of the TableModelListener interface, 
+//
+
+    // By default forward all events to all the listeners. 
+    public void tableChanged(TableModelEvent e) {
+        fireTableChanged(e);
+    }
+}
diff --git a/src/TableSorter.java b/src/TableSorter.java
new file mode 100644 (file)
index 0000000..5fc561a
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
+ */
+
+/**
+ * A sorter for TableModels. The sorter has a model (conforming to TableModel) 
+ * and itself implements TableModel. TableSorter does not store or copy 
+ * the data in the TableModel, instead it maintains an array of 
+ * integers which it keeps the same size as the number of rows in its 
+ * model. When the model changes it notifies the sorter that something 
+ * has changed eg. "rowsAdded" so that its internal array of integers 
+ * can be reallocated. As requests are made of the sorter (like 
+ * getValueAt(row, col) it redirects them to its model via the mapping 
+ * array. That way the TableSorter appears to hold another copy of the table 
+ * with the rows in a different order. The sorting algorthm used is stable 
+ * which means that it does not move around rows when its comparison 
+ * function returns 0 to denote that they are equivalent. 
+ *
+ * @version 1.9 02/06/02
+ * @author Philip Milne
+ */
+
+import java.util.*;
+
+import javax.swing.table.TableModel;
+import javax.swing.event.TableModelEvent;
+
+// Imports for picking up mouse events from the JTable. 
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.InputEvent;
+import javax.swing.JTable;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+public class TableSorter extends TableMap
+{
+    int             indexes[];
+    Vector          sortingColumns = new Vector();
+    boolean         ascending = true;
+    int compares;
+    int Xcolumn=0;
+    boolean Xascending=false;
+
+    public TableSorter()
+    {
+        indexes = new int[0]; // For consistency.        
+    }
+
+    public TableSorter(TableModel model)
+    {
+        setModel(model);
+    }
+
+    public void setModel(TableModel model) {
+        super.setModel(model); 
+        reallocateIndexes(); 
+    }
+
+    public int compareRowsByColumn(int row1, int row2, int column)
+    {
+        Class type = model.getColumnClass(column);
+        TableModel data = model;
+
+        // Check for nulls
+
+        Object o1 = data.getValueAt(row1, column);
+        Object o2 = data.getValueAt(row2, column); 
+
+        // If both values are null return 0
+        if (o1 == null && o2 == null) {
+            return 0; 
+        }
+        else if (o1 == null) { // Define null less than everything. 
+            return -1; 
+        } 
+        else if (o2 == null) { 
+            return 1; 
+        }
+
+/* We copy all returned values from the getValue call in case
+an optimised model is reusing one object to return many values.
+The Number subclasses in the JDK are immutable and so will not be used in 
+this way but other subclasses of Number might want to do this to save 
+space and avoid unnecessary heap allocation. 
+*/
+        if (type.getSuperclass() == java.lang.Number.class)
+            {
+                Number n1 = (Number)data.getValueAt(row1, column);
+                double d1 = n1.doubleValue();
+                Number n2 = (Number)data.getValueAt(row2, column);
+                double d2 = n2.doubleValue();
+
+                if (d1 > d2)
+                    return -1;
+                else if (d1 < d2)
+                    return 1;
+                else
+                    return 0;
+            }
+        else if (type == java.util.Date.class)
+            {
+                Date d1 = (Date)data.getValueAt(row1, column);
+                long n1 = d1.getTime();
+                Date d2 = (Date)data.getValueAt(row2, column);
+                long n2 = d2.getTime();
+
+                if (n1 < n2)
+                    return -1;
+                else if (n1 > n2)
+                    return 1;
+                else return 0;
+            }
+        else if (type == String.class)
+            {
+                String s1 = (String)data.getValueAt(row1, column);
+                String s2    = (String)data.getValueAt(row2, column);
+                int result = s1.compareTo(s2);
+
+                if (result < 0)
+                    return -1;
+                else if (result > 0)
+                    return 1;
+                else return 0;
+            }
+        else if (type == Boolean.class)
+            {
+                Boolean bool1 = (Boolean)data.getValueAt(row1, column);
+                boolean b1 = bool1.booleanValue();
+                Boolean bool2 = (Boolean)data.getValueAt(row2, column);
+                boolean b2 = bool2.booleanValue();
+
+                if (b1 == b2)
+                    return 0;
+                else if (b2) // Define false > true
+                    return 1;
+                else
+                    return -1;
+            }
+        else
+            {
+                Object v1 = data.getValueAt(row1, column);
+                String s1 = v1.toString();
+                Object v2 = data.getValueAt(row2, column);
+                String s2 = v2.toString();
+                int result = s1.compareTo(s2);
+
+                if (result < 0)
+                    return -1;
+                else if (result > 0)
+                    return 1;
+                else return 0;
+            }
+    }
+
+    public int compare(int row1, int row2)
+    {
+        compares++;
+        for(int level = 0; level < sortingColumns.size(); level++)
+            {
+                Integer column = (Integer)sortingColumns.elementAt(level);
+                int result = compareRowsByColumn(row1, row2, column.intValue());
+                if (result != 0)
+                    return ascending ? result : -result;
+            }
+        return 0;
+    }
+
+    public void  reallocateIndexes()
+    {
+        int rowCount = model.getRowCount();
+
+        // Set up a new array of indexes with the right number of elements
+        // for the new data model.
+        indexes = new int[rowCount];
+
+        // Initialise with the identity mapping.
+        for(int row = 0; row < rowCount; row++)
+            indexes[row] = row;
+    }
+
+    public void tableChanged(TableModelEvent e)
+    {
+        //System.out.println("Sorter: tableChanged"); 
+        reallocateIndexes();
+
+        sortByColumn(Xcolumn, Xascending); 
+        super.tableChanged(e);
+    }
+
+    public void checkModel()
+    {
+        if (indexes.length != model.getRowCount()) {
+            //System.err.println("Sorter not informed of a change in model.");
+        }
+    }
+
+    public void  sort(Object sender)
+    {
+        checkModel();
+
+        compares = 0;
+        // n2sort();
+        // qsort(0, indexes.length-1);
+        shuttlesort((int[])indexes.clone(), indexes, 0, indexes.length);
+        //System.out.println("Compares: "+compares);
+    }
+
+    public void n2sort() {
+        for(int i = 0; i < getRowCount(); i++) {
+            for(int j = i+1; j < getRowCount(); j++) {
+                if (compare(indexes[i], indexes[j]) == -1) {
+                    swap(i, j);
+                }
+            }
+        }
+    }
+
+    // This is a home-grown implementation which we have not had time
+    // to research - it may perform poorly in some circumstances. It
+    // requires twice the space of an in-place algorithm and makes
+    // NlogN assigments shuttling the values between the two
+    // arrays. The number of compares appears to vary between N-1 and
+    // NlogN depending on the initial order but the main reason for
+    // using it here is that, unlike qsort, it is stable.
+    public void shuttlesort(int from[], int to[], int low, int high) {
+        if (high - low < 2) {
+            return;
+        }
+        int middle = (low + high)/2;
+        shuttlesort(to, from, low, middle);
+        shuttlesort(to, from, middle, high);
+
+        int p = low;
+        int q = middle;
+
+        /* This is an optional short-cut; at each recursive call,
+        check to see if the elements in this subset are already
+        ordered.  If so, no further comparisons are needed; the
+        sub-array can just be copied.  The array must be copied rather
+        than assigned otherwise sister calls in the recursion might
+        get out of sinc.  When the number of elements is three they
+        are partitioned so that the first set, [low, mid), has one
+        element and and the second, [mid, high), has two. We skip the
+        optimisation when the number of elements is three or less as
+        the first compare in the normal merge will produce the same
+        sequence of steps. This optimisation seems to be worthwhile
+        for partially ordered lists but some analysis is needed to
+        find out how the performance drops to Nlog(N) as the initial
+        order diminishes - it may drop very quickly.  */
+
+        if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) {
+            for (int i = low; i < high; i++) {
+                to[i] = from[i];
+            }
+            return;
+        }
+
+        // A normal merge. 
+
+        for(int i = low; i < high; i++) {
+            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
+                to[i] = from[p++];
+            }
+            else {
+                to[i] = from[q++];
+            }
+        }
+    }
+
+    public void swap(int i, int j) {
+        int tmp = indexes[i];
+        indexes[i] = indexes[j];
+        indexes[j] = tmp;
+    }
+
+    // The mapping only affects the contents of the data rows.
+    // Pass all requests to these rows through the mapping array: "indexes".
+
+    public Object getValueAt(int aRow, int aColumn)
+    {
+        checkModel();
+        return model.getValueAt(indexes[aRow], aColumn);
+    }
+
+    public void setValueAt(Object aValue, int aRow, int aColumn)
+    {
+        checkModel();
+        model.setValueAt(aValue, indexes[aRow], aColumn);
+    }
+
+    public void sortByColumn(int column) {
+        sortByColumn(column, true);
+    }
+
+    public void sortByColumn(int column, boolean ascending) {
+        this.ascending = ascending;
+        sortingColumns.removeAllElements();
+        sortingColumns.addElement(new Integer(column));
+        sort(this);
+        super.tableChanged(new TableModelEvent(this)); 
+    }
+
+    // There is no-where else to put this. 
+    // Add a mouse listener to the Table to trigger a table sort 
+    // when a column heading is clicked in the JTable. 
+    public void addMouseListenerToHeaderInTable(JTable table) { 
+        final TableSorter sorter = this; 
+        final JTable tableView = table; 
+        tableView.setColumnSelectionAllowed(false); 
+        MouseAdapter listMouseListener = new MouseAdapter() {
+            public void mouseClicked(MouseEvent e) {
+                TableColumnModel columnModel = tableView.getColumnModel();
+                int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 
+                int column = tableView.convertColumnIndexToModel(viewColumn); 
+                if(e.getClickCount() == 1 && column != -1) {
+                    //System.out.println("Sorting ..."); 
+                    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; 
+                    boolean ascending = (shiftPressed == 0); 
+                    sorter.sortByColumn(Xcolumn=column, Xascending=ascending); 
+                }
+             }
+         };
+        JTableHeader th = tableView.getTableHeader(); 
+        th.addMouseListener(listMouseListener); 
+    }
+
+
+
+}
diff --git a/src/manifest.txt b/src/manifest.txt
new file mode 100644 (file)
index 0000000..26029e3
--- /dev/null
@@ -0,0 +1 @@
+Main-Class: Main\r