Additional Code - Zip file

Listing 1: Client for Prime Scenario example

             public class PrimeScenarioExampleClient
               { 
                  public void runPrimeScenario()
                  {
                     try {
                        // Create a VirtualSocket and connect it to MasterServerSocket.
                        Socket v1 = new VirtualSocket("localhost", 5555);
   
                        // Do some asynchronous input in a separate thread.
                        new AsynchronousThread(v1).start();
   
                        // Do some synchronous communication.
                        ObjectOutputStream oos = new ObjectOutputStream(v1.getOutputStream());
                        ObjectInputStream ois = new ObjectInputStream(v1.getInputStream());
                        oos.writeObject(new Integer(3)); 
                        Integer i1 = (Integer) ois.readObject();
                        v1.close();
                     }
                     catch (Exception e) {}
                  }
   
                  class AsynchronousThread extends Thread                                                                    
                  {
                     private Socket virtualSocket;
   
                     AsynchronousThread(Socket virtualSocket)
                     {
                        this.virtualSocket = virtualSocket;
                     }
                     
                     public void run()
                     {
                        try {
                           // Create a VirtualServerSocket that shares a port with virtualSocket.
                           // (Note that it will be connected by virtue of joining a connected socket group.)
                           ServerSocket serverSocket = new VirtualServerSocket(virtualSocket.getLocalPort());
   
                           // Create a VirtualSocket that shares a port with virtualSocket.
                           serverSocket.setSoTimeout(10000);
                           Socket v4 = serverSocket.accept();
   
                           // Get an object from the server.
                           v4.setSoTimeout(10000);
                           ObjectInputStream ois = new ObjectInputStream(v4.getInputStream());
                           Object o = ois.readObject();
                           serverSocket.close();
                           v4.close();
                        }
                        catch (Exception e) {}
                     }
                  }
   
                  public static void main(String[] args)
                  {
                     new PrimeScenarioExampleClient().runPrimeScenario();
                  }
               }


Listing 2: Server for Prime Scenario example

             public class PrimeScenarioExampleServer
               {
                  public void runPrimeScenario()
                  {
                     try {
                        // Create a MasterServerSocket and get a VirtualSocket.
                        ServerSocket serverSocket = new MasterServerSocket(5555);
                        serverSocket.setSoTimeout(10000);
                        Socket v2 = serverSocket.accept();
      
                        // Do some asynchronous communication in a separate thread.
                        Thread asynchronousThread = new AsynchronousThread(v2);
                        asynchronousThread.start();
      
                        // Do some synchronous communication.
                        ObjectInputStream ois = new ObjectInputStream(v2.getInputStream());
                        ObjectOutputStream oos = new ObjectOutputStream(v2.getOutputStream());
                        v2.setSoTimeout(10000);
                        Object o = ois.readObject();
                        oos.writeObject(o);

                        serverSocket.close();
                        v2.close();
                     }
                     catch (Exception e) { }
                  }
      
                  class AsynchronousThread extends Thread
                  {
                     private Socket virtualSocket;
      
                     public AsynchronousThread(Socket socket) throws IOException
                     {this.virtualSocket = socket;}
      
                     public void run()
                     {
                        try {
                           // Connect to VirtualServerSocket.
                           Thread.sleep(2000);
                           String hostName = virtualSocket.getInetAddress().getHostName();
                           int port = virtualSocket.getPort();
                           Socket v3 = new VirtualSocket(hostName, port);
      
                           // Send an object to the client.
                           ObjectOutputStream oos = new ObjectOutputStream(v3.getOutputStream());
                           oos.writeObject(new Integer(7));
      
                           oos.flush();
                           v3.close();
                        }
                        catch (Exception e) {}
                     }
                  }
      
                  public static void main(String[] args)
                  {
                     new PrimeScenarioExampleServer().runPrimeScenario();
                  }
               }



Listing 3

1. Add org.apache.commons.net.ftp.VirtualSocketFactory class:

 	package org.apache.commons.net.ftp;
	
	import java.io.IOException;
	import java.net.InetAddress;
	import java.net.ServerSocket;
	import java.net.Socket;
	import java.net.UnknownHostException;
	import org.apache.commons.net.SocketFactory;
	import org.jboss.remoting.transport.multiplex.VirtualServerSocket;
 	import org.jboss.remoting.transport.multiplex.VirtualSocket;
  
	public class VirtualSocketFactory implements SocketFactory
 	{
  
		public Socket createSocket(String host, int port) throws UnknownHostException, IOException
 		{
    		return new VirtualSocket(host, port);
  	}

  
		public Socket createSocket(InetAddress address, int port) throws IOException
  	{ 
    		return new VirtualSocket(address, port);
    	}
  
    	public Socket createSocket(String host, int port, InetAddress 
		localAddr, int localPort) 
		throws UnknownHostException, IOException
   	{
    		return new VirtualSocket(host, port, localAddr, localPort);
    	}
    	
		public Socket createSocket(InetAddress address, int port, InetAddress localAddr, int localPort)
    throws IOException
    {
    		return new VirtualSocket(address, port, localAddr, localPort);
   	}
    	
		public ServerSocket createServerSocket(int port) throws IOException
    {
   		return new VirtualServerSocket(port);
    }
   
		public ServerSocket createServerSocket(int port, int backlog) 
		throws IOException
    {
    		return new VirtualServerSocket(port, backlog);
    }
    
		public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException
    {
    		return new VirtualServerSocket(port, backlog, bindAddr);
    }
}

2. Derive org.apache.commons.net.ftp.FTPVirtualClient from org.apache.commons.net.ftp.FTPClient and set socket factory to
 VirtualSocketFactory in the constructor:

		package org.apache.commons.net.ftp;
		
		public class FTPVirtualClient extends FTPClient
    {
    		public FTPVirtualClient()
     	{
    			super();
    			setSocketFactory(new VirtualSocketFactory());
    		}
    	}

3. Modify examples.ftp to use FTPVirtualClient (and also to use active mode):

  
		package examples;
 		import java.io.FileInputStream;
 		import java.io.FileOutputStream;
   	import java.io.IOException;
   	import java.io.InputStream;
   	import java.io.OutputStream;
   	import java.io.PrintWriter;
    	import org.apache.commons.net.ftp.FTP;
   	import org.apache.commons.net.ftp.FTPClient;
 		import org.apache.commons.net.ftp.FTPVirtualClient;
 		import org.apache.commons.net.ftp.FTPConnectionClosedException;
 		import org.apache.commons.net.ftp.FTPReply;
        
 		/ ***
      * This is an example program demonstrating how to use the FTPClient class.
      * This program connects to an FTP server and retrieves the specified
   * file.  If the -s flag is used, it stores the local file at the FTP server.
   * Just so you can see whatÕs happening, all reply strings are printed.
   * If the -b flag is used, a binary transfer is assumed (default is ASCII).
   *
   * Usage: ftp [-s] [-b] <hostname> <username> <password> <remote file> <local file>
   * 
   ***/
  public final class ftp
  {
       .
       .
       .
 
     public static final void main(String[] args)
    	{ 
       .
       .
       .
       FTPClient ftp;
       .
      	.
      	.
      	//ftp = new FTPClient();
      	ftp = new FTPVirtualClient();
      	ftp.addProtocolCommandListener(new PrintCommandListener(newPrintWriter(System.out)));
      	.
      	.
      	.

	__main:
      	try
      {
         	.
         	.
         	.
        	// Use passive mode as default because most of us are
        	// behind firewalls these days.
         	// ftp.enterLocalPassiveMode();
         	ftp.enterLocalActiveMode();
         	.
        	.
         	.
      	}
     	.
      	.
     	.
    } // end main
}
       

4. Change a call in FTPClient to bind the server socket to the same port used by the socket that transmits commands to the server:

		/**
		* Establishes a data connection with the FTP server, returning
		* a Socket for the connection if successful.  If a restart
   	* offset has been set with {@link #setRestartOffset(long)},
    	* a REST command is issued to the server with the offset as
		* an argument before establishing the data connection.  Active
   	* mode connections also cause a local PORT command to be issued.
  	* 
		* @param command  The text representation of the FTP command to send.
		* @param arg The arguments to the FTP command.  If this parameter is
 		* 		set to null, then the command is sent with no argument.
    	* @return A Socket corresponding to the established data connection.
 		* 		Null is returned if an FTP protocol error is reported at
    	*  	any point during the establishment and initialization of
 		*   	the connection.
   	* @exception IOException  If an I/O error occurs while either 
			sending a
    	*   command to the server or receiving a reply from the server.
    	*/
   protected Socket _openDataConnection_(int command, String arg)
     throws IOException
   {
      Socket socket;
   
      if (__dataConnectionMode != ACTIVE_LOCAL_DATA_CONNECTION_MODE &&
      		  __dataConnectionMode != PASSIVE_LOCAL_DATA_CONNECTION_MODE)
          return null;
   
      if (__dataConnectionMode == ACTIVE_LOCAL_DATA_CONNECTION_MODE)
      {
         ServerSocket server;
         System.out.println(getLocalPort());
	  //server = _socketFactory_.createServerSocket(0, 1, getLocalAddress());
         server = _socketFactory_.createServerSocket(getLocalPort(), 1, getLocalAddress());
   
            .
            .
            .
 }  

Additional Code - Zip file