November 12, 2010

Running Vuze (Azureus) BitTorrent Client From Command Line (SSH Terminal)

Introduction
Finding command line BitTorrent clients has been a challenge.  My challenge is finding one which passes the 5 minute rule.  If I want a GUI based BitTorrent client I can download and install uTorrent, click on the torrent's link, and be downloading within 5 minutes.  For command line clients, I have run into python errors, C library version issues, and other problems which are not resolved in 5 minutes and not worth the effort to.
      
Vuze (Azureus) is a major Java based GUI BitTorrent client however a little searching online revealed it can also be run from a command line.  Getting it up and running and being able to monitor the torrent download was not too painful.  It required searching to solve some problems so it did not pass the 5 minute rule but it was not too bad.  I document my research here so it is all in one place.

Download Vuze (Azureus) and supporting libraries
You need to download 3 files.  Put them all in the same directory

Vuze_<version>.jar
Select to download the "Jar" from the download page or try downloading directly.

log4j.jar 
Search and download log4j.jar or try downloading directly.

commons-cli.jar
Search and download commons-cli.jar or try downloading directly.
Running Vuze (Azureus) from the command line
To run Vuze (Azureus) from the command line, execute the following command (Linux assumed)

$ screen java -jar Vuze_4510.jar --ui=console

Yes, you will want to use the
screen command to run it.  Why you want to use screen will become apparent soon.
Console commands
The available console commands are easy enough.  Type "help" to get a list of available commands:
> -----
help
> -----
Available console commands (use help <command> for more details):

  [] xml   [#] hack   [a] add   [c] check   [q] queue   [r] remove
  [s] start   [h] stop   [] host   [] publish   [] forcestart   [tl] tlog
  [l] log   [m] move   [] share   [+] set   [sh] show   [u] ui   [] logout
  [] quit   [?] help   [] alias   [] prio   [] plugin
> -----


Type "help <command>" to get help for a specific command.  To get help for the "add" command, type "help add"
> -----
help add
add [addoptions] [.torrent path|url]            a       Add a download from the given .torrent file path or url. Example: 'add /path/to/the.torrent' or 'add http://www.url.com/to/the.torrent'
> -----
add [addoptions] [.torrent path|url]            a       Add a download from the given .torrent file path or url. Example: 'add /path/to/the.torrent' or 'add http://www.url.com/to/the.torrent'
    -r,--recurse               recurse sub-directories.
    -f,--find                  only find files, don't add.
    -h,--help                  display help about this command
    -l,--list                  list previous find results
    -o,--output <outputDir>    override default download directory
> -----

Adding a Torrent
Adding a torrent is easy.  Use the "add" command combined with either the URL or file system path to the torrent.
> -----
add http://url/of/the/file.torrent


> -----
add /path/of/the/file.torrent

Checking Progress of a Torrent
To see if a torrent is finished, use the "show torrents" command

> -----
show torrents
> -----
 1 [>] 078.2%   Something being downloaded (3.27 GB) ETA: 21h 26m
                Speed: 9.7 kB/s / 4.8 kB/s      Amount: 2.56 GB ( 1.76 MB discarded ) / 515.76 MB       Connections: 4(8) / 2(9)

 2 [>] 071.7%   Another thing being downloaded (3.49 GB) ETA: 12h 36m
                Speed: 23.8 kB/s / 5.6 kB/s     Amount: 2.51 GB ( 1.45 MB discarded ) / 270.24 MB       Connections: 5(8) / 2(8)

Total Speed (down/up): 33.5 kB/s / 10.5 kB/s
Transferred Volume (down/up/discarded): 5.08 GB / 786.01 MB / 3.21 MB
Total Connected Peers (seeds/peers): 9 / 4
> -----

Logging out of Your SSH Session and Coming Back
After you added torrent(s), you want Vuze (Azureus) to continue running in the background until it is finished but you also want to be able to come back to it to check on the progress.  So how do you do this?

Well, because the
screen command was used to start the application, to leave and let Vuze (Azureus) to continue running in the background all you need to do is close your console window or exit your Putty screen.  Basically just end your connection without exiting or logging out.
To come back and check on the progress of your torrent download is just as easy.  SSH to you account then execute the following command
$ screen -ls
There is a screen on:
        31432.pts-0.server      (Attached)
1 Socket in /var/run/screen/S-michael.
You should see a screen listed.  Now execute the following command  to return to the screen.
$ screen –x 31432

And there you have it, you are back at the Vuze (Azureus) console interface!

References
http://wiki.vuze.com/w/ConsoleUI
http://wiki.vuze.com/w/Commandline_options
http://azureus.sourceforge.net/download.php
http://sourceforge.net/projects/azureus/files/vuze/Vuze_4510/Vuze_4510.jar/download
http://svn.vuze.com/public/client/trunk/uis/lib/log4j.jar
http://svn.vuze.com/public/client/trunk/uis/lib/commons-cli.jar

March 06, 2003

Distributed Notification with Java RMI

Abstract

Java’s implementation of Remote Method Invocation (RMI) is very easy to use and very power. Java makes the task of setting up an RMI server an almost trivial one. Once running, connecting client applications to the RMI server is also a breeze. There are examples and how-tos for client to server communication everywhere. But what about the other way, server to client communication? Is it possible for an RMI server to actively communicate with all the clients that are connected to it without the client initiating the conversation? In other words, is distributed notification possible? The purpose of this post is to demonstrate that yes, it is possible.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Problem

Consider development of a small test application that demonstrates an RMI server notifying its clients of events. A very simple example is an RMI “time server”. Clients register with the server (client to server communication) and then every second all registered clients are notified of an event, the new date and time (server to client communication). The client implements some kind of listener and that listener can be used to handle the event any way the client sees fit.

Proposed Solution

The difficulty that I have with implementing distributed notification is that the server has to have some knowledge of the client application. Just as the client needs an Xxx_Stub.class to talk to the server, the server needs a similar Xxx_Stub.class to talk to the client.

The first, and most obvious (to me anyway) solution was for the client to develop its own remote class, generate an Xxx_Stub.class for it, then give that Xxx_Stub.class file to the server. Not a very attractive solution.

After struggling with the problem for a while I narrowed down the root of the problem. On the server side, I had interfaces and objects like listing 1 and listing 2.

Listing 1 - ClientCallback interface

public interface ClientCallback extends Remote {
    public void informClient(String msg)
    throws RemoteException;
}

Listing 2 - Remote service allowing clients to register

class SomeServiceImpl extends UnicastRemoteObject implements SomeService {
    public void registerWithService(ClientCallback cc)
    throws RemoteException {
        //...
    }
}

Continuing with the root of the problem, on the client side I want to make a remote call that looks something like listing 3.

Listing 3 - What client wants to do

serverObject.registerWithService(this);

The root of the problems caused by this code is that the client would then have to become a ‘server’ itself, generating Xxx_Stub.class files for the classes that implement ClientCallback and somehow getting those Xxx_Stub classes to the server. Not very pretty.

When considering a solution to this problem, realization struck. The server would have no problems if the class that implemented ClientCallback was a class that the server had created! For example, let us say that the server gives to the client the class in listing 4.

Listing 4 - Server gives client this class

class ServerListener implements ClientCallback {
   /**
    * constructor
    */
   public ServerListener(String serverName, int port)
   throws Exception {
      UnicastRemoteObject.exportObject( this );

      SomeService ss = (SomeService)Naming.lookup("rmi://<server>:<port>/SomeService");

      ss.registerWithService(this);
   }


   /**
    * MyCustomListener interface method
    */
   public void informClient(String msg) {
     // do something
   }
}

When the code for the RMI server is compiled, a ServerListener_Stub.class is also created and bundled in the jar file for the client to use. Basically, this is an object that a client can create an instance of just like any other Java object.

ServerListener ls = new ServerListener("localhost", 1099);

This object knows how to contact the RMI server, do the appropriate lookup, and register itself with the server. And because of the line:

UnicastRemoteObject.exportObject(this); 

The server is able to call the informClient() method on the client’s machine! Bingo! that’s exactly what I wanted!

Well not quite. The server can now inform the client of something, but that code is buried inside the ServerListener object that the client really has no access to. Extending the ServerListener object won’t work because that gets you back to the previous problem of the server having to know what the client classes are. Here’s my solution, another listener interface provided by the server!

Let’s say the ClientCallback interface had an analogous, non-remote interface called ClientListener. Also let’s say that the ServerListener class that the server provides as an additional method that looks like listing 5.

Listing 5 - Method to register client-side listener

Vector listeners = new Vector();

public void addClientListener(ClientListener cl) {
    if (!listeners.contains(cl)) {
        listeners.add(cl);
    }
}

Now let ClientListener be just a simple, non-remote interface as in listing 6.

Listing 6 - Non-remote, client-side interface

public interface ClientListener() {
    public void statusChanged(String s);
}

Now the client side code just falls into place as in listing 7.

Listing 7 - Client code

// create an object that can "listen" for events on the server
ServerListener sl = new ServerListener("localhost", 1099);

// add as many classes as you want to handle those events
sl.addClientListener(new ClientListenerA());
sl.addClientListener(new ClientListenerB());
sl.addClientListener(new ClientListenerC());
sl.addClientListener(new ClientListenerD());

The implementation of the ServerListener.informClient() object is nothing more than looping over the list of ClientListener objects and calling the changeStatus() method on each.

March 05, 2003

Drag & Drop With Java GUI Components

Abstract

The Java programming language is very powerful. In my opinion, it has brought the art of programming back to programmers by focusing on fundamentals such as data structures, reusable code, and application design. Though, like all programming languages, Java is not perfect. GUI development with Java can be frustrating at times. This is especially true in Window and Apple environments where Drag & Drop is pervasive. An application that does not properly participate in Drag & Drop can become quite frustrating to work with. Java applications are usually frustrating to use for this reason. The purpose of this paper is to tell my story about Java and Drag & Drop; to relay what I have learned and hopefully give readers of this post a jump start in their own development.

Disclaimer

This post is solely informative. Critically think before using any information presented. Learn from it but ultimately make your own decisions at your own risk.

Drag & Drop - My Experience

Where are the listeners?

For a developer, the first instinct for doing Drag & Drop would be to start looking at the listeners for the mouse, in fact looking at anything mouse related. This is futile though because, surprisingly, the implementation of Drag & Drop is not found in anything mouse related!

The place to start looking is the java.awt.dnd package. It is here that can be found all the tools needed to implement Drag & Drop. However the classes and interfaces here are quite confusing. Worse yet, documentation and examples are scarce as well.

The most confusing part of Drag & Drop in Java is that it needs to be developed by a programmer not simply implemented. Here is what that statement means. Programmers typically implement GUI events in Java by implementing a listener and assigning the listener to the object. Take JButton for example. An ActionListener is implemented and then assigned to a JButton instance using the addActionListener() method. When the button is pressed, the method implemented in the listener is run. Because listeners are used everywhere in the Java GUI APIs, it is natural to assume that Drag & Drop is also like this - Find the Drag & Drop listener, plug it in, and the work is done. Sadly this is not the case. A lot more development is needed to implement Drag & Drop.

Step by step

The first step in making any Java component able to do Drag & Drop is to create a new object that extends the existing one. This needs to be done because additions need to be made to the existing component. For example, create a new class, MyJTree that extend JTree.

Next, jump to the java.awt.dnd package. There are the 3 objects to start off with:

  • DragSource
  • DropTarget
  • DragGestureRecognizer

If I want to drag from MyJTree, then I need to add a private DragSource dragsource; to the MyJTree class. That is the simple explanation of what DragSource is for. If I want to drop onto MyJTree, then I need to add a private DropTarget droptarget; to the MyJTree class. That is the simple explanation of what DropTarget is for. Finally, for these two objects to be used, a DragGestureRecognizer needs to be used, so add a private DragGestureRecognizer dgr; to MyJTree.

Adding these three objects to MyJTree creates a new component that has the potential to:

  1. Recognize that a drag event has started by using DragGestureRecognizer
  2. Start dragging something by using DragSource
  3. Accept the drop of something by using DropTarget

But how should MyJTree respond when these events occur? Your developer instincts might be saying that the responses should be an implementation of some listener. This is absolutely correct! In fact, there are 3 listeners, one for each of the three objects just added to MyJTree:

  1. DragGestureListener
  2. DropTargetListener
  3. DragSourceListener

So, putting it all together, this is how drag & drop might be implemented:

Overload the default constructor for the MyJTree class. Create an instance of DragSource by calling its constructor. Using the DragSource object just created, call the createDefaultDragGestureRecognizer() method. This method requires an implementation of the DragGestureListener, which is one of the three listeners that need to be implemented. Also the Component c parameter of that method is the component that the recognizer is for, in other words the keyword this, MyJTree. Finally a DropTarget is constructed, calling its constructor, again using MyJTree (keyword this) for the Component parameter and an implementation of the DropTargetListener. It is a good idea to first make three blank listeners (have all the methods but the methods do not do anything), get everything set in MyJTree, then make sure everything compiles. Once that is done, move onto implementing the methods in the listeners so a Drag & Drop operation can be done.

By this time MyJTree has been developed with three objects from java.awt.dnd and those objects have been created (In MyJTree) utilizing one of their various overloaded constructors and blank implementations of their listeners. At this point implementing those listener methods is all that is left in creating a GUI component capable of performing Drag & Drop operations.

Walkthrough

Everything starts with the DragGestureListener.dragGestureRecognized() method. When a user starts to drag something on MyJTree the DragGestureListener hears it and fires the dragGestureRecognized() method.

NOTE At this time dragging has not begun yet.

The DragGestureListener has simply recognized that the user wants to start dragging. It calls dragGestureRecognized() to figure out what to do.

What the dragGestureRecognized() method needs to do is figure out whether or not a drag should begin, and if so, start it. Any code needed can be added to determine if a drag should start (Perhaps there are some nodes on MyJTree that should never be dragged). If a drag should start, dragGestureRecognized() needs to use its DragGestureEvent parameter and do something like:

Evnt.getDragSource().startDrag(evnt, someCursor, someTransferable, someDragSourceListener

The getDragSource() method will get the DragSource object added to MyJTree, and calling the startDrag() method will finally start a drag.

At this point, while dragging continues, the execution of Java code will wildly flip back and forth between the DragSourceListener and the DropTargetListener. The methods in these listeners are fairly self-explanatory. Here is a typical manner in which the methods are used:

  • DragSourceListener.dragOver() – Used to change the display of the mouse.
  • DropTargetListener.dragEnter() – Figures out if the target will accept a drop or not. If not, the Drag & Drop operation is canceled.
  • DropTargetListener.dragOver() – Changes the display of the object being dropped on (highlighting tree nodes for example).
  • DropTargetListener.drop() – Most important! Run when the mouse button is finally released and a user makes a drop.

DropTargetListener.drop() needs to do two things. One, at the end of the method it needs to use its DropTargetDropEvent parameter and call:

Evnt.getDropTargetContext().dropComplete(true);

This will end the Drag & Drop operation that began with DragGestureListener.dragGestureRecognized(). Two, before the drop method calls dropComplete(true) it needs to get what is being dragged and do something with it! Otherwise what is the point of dragging and dropping?

How does the drop() method know what was is being dropped? Looking at the DragGestureListener.dragGestureRecognized() method. At some point, the call:

Evnt.getDragSource().startDrag(evnt, someCursor, someTransferable, someDragSourceListener)

was made to start the drag. The object someTransferable is what is being dragged and can be any Java object as long as it, and all objects in it, implement the Transferable and Serializable interfaces. Think of the Transferable as an invisible connection between what was dragged from and what was dropped on.

At startDrag() a 100% complete !!copy!! is made of the object passed to the method as the Transferable. The fact that it is a !!copy!! is very important to know because in DropTargetListener.drop(), the Transferable gotten from the DropTargetDropEvent parameter does not reference the original object set as the Transferable. For example, if a TreeNode is dragged and that TreeNode implements Transferable and is set as the Transferable in startDrag() the TreeNode gotten in drop() is not simply a reference to the one on the source tree. It is a completely new object with the same information from the source tree copied exactly!! This is very important, especially when nodes need to be added/deleted from the tree. The original nodes in the tree need to be found from the copy in the Transferable.

Finally, in the drop() method, anything that needs to be done can be done to perform all the operations required for a successful drop, including contacting a database to perform inserts, updates, and deletions to tables.

Tip about Applets

Web browsers have a peculiar feature. A perfectly implemented Drag & Drop component will fail to do any Drag & Drop of any kind if the component is created in the Applet.start() method. When it is created here, for some reason the web browser itself will listen for Drag & Drop operations and all the code that has been developed for the Drag & Drop component will never be run. What is needed to overcome this problem is to create the GUI of the JApplet in a separate thread. This is not difficult to do. Simply move all the code that is in the Applet.start() method to a run() method, have the JApplet class implement Runnable, and in the Applet.start() method do something like:

Thread t = new Thread(this);
t.start();

This sounds very strange but it is the only way to have the code developed for the Drag & Drop component actually run without drag gestures being intercepted by the web browser.