Index: gli/trunk/src/org/greenstone/gatherer/download/DownloadJob.java
===================================================================
--- gli/trunk/src/org/greenstone/gatherer/download/DownloadJob.java	(revision 17508)
+++ gli/trunk/src/org/greenstone/gatherer/download/DownloadJob.java	(revision 17525)
@@ -76,5 +76,5 @@
 
     private String download_url = "";
-
+    
     //    private String current_url;
     //    private String destination;
@@ -96,9 +96,16 @@
     public static int DEFINED_MAX  = 1;
     public static int UNDEFINED_MAX  = 2;
-
+    
+    // To prematurely terminate wget, we will need to use sockets and find a free port.
+    // We will look at a limited range of ports. This range will be reused (circular buffer)
+    private static final int PORT_BASE = 50000;
+    private static final int PORT_BLOCK_SIZE = 100;   
+    private static int nextFreePort = PORT_BASE;  // Keep track what port numbers we have checked for availability
+    int port;                                     // package access. The socket port number this instance of DownloadJob will use
+    
     private String mode = null;
    
     private String proxy_url;
-
+    
     /**
      */
@@ -169,5 +176,5 @@
 	// The stop_start_button is used to alternately start or stop the
 	// job. If the current state of the job is paused then this
-	// restart is logically equivelent to a resume.
+	// restart is logically equivalent to a resume.
 	if(event.getSource() == progress.stop_start_button) {
 	    previous_state = state;
@@ -189,4 +196,36 @@
     }
 
+    /** Given a portnumber to check, returns true if it is available
+     * (if nothing's listening there already). */
+    public static boolean isPortAvailable(int portnum) {
+	Socket tmpSocket = null;
+	try {
+	    tmpSocket = new Socket("localhost", portnum);
+	    tmpSocket.close();
+	    return false;
+
+	} catch(ConnectException ex){
+	    // "Signals that an error occurred while attempting to connect a socket 
+	    // to a remote address and port. Typically, the connection was refused
+	    // remotely (e.g., no process is listening on the remote address/port)."
+	    System.err.println("Port " + portnum + " not yet in use.");
+	    tmpSocket = null;
+	    return true;
+
+	} catch(Exception ex) { 
+	    // includes BindException "Signals that an error occurred while attempting
+	    // to bind a socket to a local address and port. Typically, the port is in
+	    // use, or the requested local address could not be assigned."
+	    tmpSocket = null;
+	    return false;
+	}
+    }
+
+    /** Circular buffer. Modifies the value of nextFreePort (the buffer index). */
+    private void incrementNextFreePort() {
+	int offset = nextFreePort - PORT_BASE;
+	offset = (offset + 1) % PORT_BLOCK_SIZE;
+	nextFreePort = PORT_BASE + offset;
+    } 
 
     public void callDownload() {
@@ -202,4 +241,9 @@
 	command_list.add("-cache_dir");
 	command_list.add(Gatherer.getGLIUserCacheDirectoryPath());
+	// For the purposes of prematurely terminating wget from GLI (which creates a socket
+	// as a communication channel between GLI and Perl), it is important to tell the script
+	// that we're running as GLI. Because when running from the command prompt, it should
+	// not create this socket and do the related processing.
+	command_list.add("-gli");
 	
 	ArrayList all_arg = download.getArguments(true,false);
@@ -252,17 +296,63 @@
 		}
 	    }
- 
 	    //System.out.println(newcmd);	    
 
-	    InputStreamReader isr = new InputStreamReader(prcs.getErrorStream());
-	    BufferedReader br = new BufferedReader(isr);
-	    // Capture the standard error stream and seach for two particular occurances.
+	    // Can use the following if debugging WgetDownload.pm - Reads debug stmts from the perl process' STDIN stream
+	    //(new PerlReaderThread(prcs)).start();
+
+	    InputStream is = prcs.getInputStream();
+	    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+
+	    // To be able to stop Wget, we use sockets to communicate with the perl process that launched wget
+	    if (!mode.equals("Z3950") && !mode.equals("SRW")) { // wget-based Download modes (OAI, MediaWiki and Web download)
+		
+		// Need to find an available (unused) port within the range we're looking for to pass it
+		// the Perl child process, so that it may set up a listening ServerSocket at that port number
+		try {
+		    boolean foundFreePort = false;
+		    for(int i = 0; i < PORT_BLOCK_SIZE; i++) {
+
+			if(isPortAvailable(nextFreePort)) {
+			    foundFreePort = true;
+			    break;
+			    
+			} else {
+			    incrementNextFreePort();
+			}
+		    }
+		    
+		    if(foundFreePort) {
+			// Free port number currently found becomes the port number of the socket that this
+			// DownloadJob instance will be connecting to when the user wants to prematurely stop Wget.
+			this.port = nextFreePort;
+			incrementNextFreePort();
+			
+		    } else {
+			throw new Exception("Cannot find an available port in the range " 
+					    + PORT_BASE + "-" + (PORT_BASE+PORT_BLOCK_SIZE)
+					    + "\nwhich is necessary for forcibly terminating wget.");
+		    }
+
+		    // Communicate the chosen port for this DownloadJob instance to the perl process, so
+		    // that it can set up a ServerSocket at that port to listen for any signal to terminate wget
+		    OutputStream os = prcs.getOutputStream();
+		    String p = ""+this.port+"\n";
+		    System.err.println("Portnumber found: " + p);
+
+		    os.write(p.getBytes());
+		    os.close();
+		  
+		} catch(Exception ex) {
+		    System.err.println("Sent available portnumber " + this.port + " to process' outputstream.\nBut got exception: " + ex);
+		}
+	    }
+	    
+	    BufferedReader br = new BufferedReader(new InputStreamReader(prcs.getErrorStream()));
+	    // Capture the standard error stream and search for two particular occurrences.
 	    String line="";
 	    boolean ignore_for_robots = false;
 	    int max_download = DownloadJob.UNKNOWN_MAX;
-
-
+	   
 	    while ((line = br.readLine()) != null && !line.trim().equals("<<Finished>>") && state != STOPPED) {
-
 		if ( max_download == DownloadJob.UNKNOWN_MAX) {
 		    if(line.lastIndexOf("<<Defined Maximum>>") != -1) {
@@ -356,8 +446,53 @@
 	    }
 	    if(state == STOPPED) {
-		isr.close();
-		prcs.destroy(); // This doesn't always work, but it's worth a try
+		// When GLI is working with wget-based download modes (OAI, MediaWiki and Web download)
+		// and the STOP button has been pressed, wget needs to be prematurely terminated.
+		// The presence of the tmpfile will indicate to the perl script that it's time to kill wget.
+		if(prcs != null && !mode.equals("Z3950") && !mode.equals("SRW")) { 
+		    
+		    // create a socket to the perl child process and communicate the STOP message
+		    Socket clientSocket = null;
+		    if(clientSocket == null) {
+			try {
+			    clientSocket = new Socket("localhost", this.port); // connect to the port chosen for this DownloadJob instance
+			    
+			    BufferedReader clientReader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+			    String response = clientReader.readLine(); // see if we've been connected
+			    System.err.println("Communicating with perl download script on port " + this.port 
+					       + "\nGot response from perl: " + response); 
+			    
+			    // Send the STOP signal
+			    OutputStream os = clientSocket.getOutputStream();
+			    String message = "<<STOP>>\n";
+			    os.write(message.getBytes());
+			    response = clientReader.readLine(); // see whether the stop signal has been received
+			    System.err.println("GLI sent STOP signal to perl to terminate wget." 
+					       + "\nGot response from perl: " + response);
+			    os.close();
+			    
+			    clientReader.close();
+			    clientSocket.close(); // close the clientSocket (the Perl end will close the server socket that Perl opened)
+			    clientReader = null;
+			    clientSocket = null;
+			} catch(IOException ex) {
+			    System.err.println("Tried to communicate through client socket - port " + this.port + ", but got exception: " + ex);
+			} catch(Exception ex) {
+			    System.err.println("Tried to open client socket, but got exception: " + ex);
+			}
+		    }
+		}
+		
+		//prcs.getInputStream().close();
+		prcs.getErrorStream().close();
+		prcs.destroy(); // This doesn't always work, but it's worth a try		
+		prcs = null;
+		br.close();
+		br = null;
+
+		// Notify the DownloadScrollPane which is waiting on this job to complete that we are ready 
+		synchronized(this) {
+		    this.notify();
+		}
 	    }
-	   
 	}
 	catch (Exception ioe) {
@@ -372,9 +507,7 @@
 	    previous_state = state;
 	    state = DownloadJob.COMPLETE;
-	    
 	}
 	// refresh the workspace tree
  	Gatherer.g_man.refreshWorkspaceTree(WorkspaceTree.DOWNLOADED_FILES_CHANGED);
-       
     }
 
@@ -464,3 +597,33 @@
 	progress.updateProgress(current, expected);
     }
+
+    
+    // Inner thread class that reads from process downloadfrom.pl's errorstream
+    private class PerlReaderThread extends Thread {
+	Process prcs = null;
+
+	public PerlReaderThread(Process proc) {
+	    this.prcs = proc;
+	}
+
+	public void run() {
+	    try {
+		if(prcs != null) {
+		    String message = null;
+		    BufferedReader eReader = new BufferedReader(new InputStreamReader(prcs.getInputStream()));
+		    while(prcs != null && (message = eReader.readLine()) != null) {
+			System.err.println("**** Perl STDOUT: " + message);
+		    }
+		    
+		    if(prcs != null && eReader != null) {
+			eReader.close();
+			eReader = null;
+			System.err.println("**** Perl ENDed.");
+		    }
+		}
+	    } catch(Exception e) {
+		System.err.println("Thread - caught exception: " + e);
+	    }
+	}
+    }
 }
