Index: trunk/gli/src/org/greenstone/gatherer/Gatherer.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/Gatherer.java	(revision 10250)
@@ -50,4 +50,5 @@
 import org.greenstone.gatherer.util.StaticStrings;
 import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.ZipTools;
 
 
@@ -159,5 +160,5 @@
 		    //   for documented example collections so "base this on
 		    //   existing collection" works
-		    Utility.unzipFromJar(Utility.COLLECT_ZIP, gli_user_directory.toString());
+		    ZipTools.unzipFromJar(Utility.COLLECT_ZIP, gli_user_directory.toString());
 		}
 		else {
@@ -189,5 +190,5 @@
 	    if (!metadata_directory.exists()) {
 		// dig out metadata.zip from JAR file and unzip it
-		Utility.unzipFromJar(Utility.METADATA_ZIP, gli_user_directory.toString());
+		ZipTools.unzipFromJar(Utility.METADATA_ZIP, gli_user_directory.toString());
 	    }
 
Index: trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java	(revision 10250)
@@ -40,4 +40,5 @@
 import org.greenstone.gatherer.RemoteGreenstoneServer;
 import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.ZipTools;
 import org.w3c.dom.*;
 import org.xml.sax.*;
@@ -232,5 +233,5 @@
 	    //If the GLI is running as an applet, and Format Features or Cross-Collection Searching have changed,
 	    //upload etc/collect.cfg to the server to immediately reflect these changes.
-	    Utility.zipup(Gatherer.getCollectDirectoryPath(), collection_name, Utility.CONFIG_FILE, null, "", "");
+	    ZipTools.zipup(Gatherer.getCollectDirectoryPath(), collection_name, Utility.CONFIG_FILE, null, "", "");
 	    RemoteGreenstoneServer.upload_url_zip(collection_name, "etc", "", null);
 	}
Index: trunk/gli/src/org/greenstone/gatherer/gui/CreatePane.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/gui/CreatePane.java	(revision 10250)
@@ -53,4 +53,5 @@
 import org.greenstone.gatherer.collection.Collection;
 import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.ZipTools;
 import org.greenstone.gatherer.shell.GBasicProgressMonitor;
 import org.greenstone.gatherer.shell.GBuildProgressMonitor;
@@ -689,5 +690,5 @@
 		else if(rebuildTypeRequired == CollectionDesignManager.BUILDCOL) {
 		    //First upload the collect.cfg file
-		    Utility.zipup(Gatherer.getCollectDirectoryPath(), collection_name, Utility.CONFIG_FILE, null, "", "");
+		    ZipTools.zipup(Gatherer.getCollectDirectoryPath(), collection_name, Utility.CONFIG_FILE, null, "", "");
 		    RemoteGreenstoneServer.upload_url_zip(collection_name, "etc", "", null);
 
Index: trunk/gli/src/org/greenstone/gatherer/shell/GShell.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/shell/GShell.java	(revision 10250)
@@ -57,4 +57,6 @@
 import org.greenstone.gatherer.util.StaticStrings; 
 import org.greenstone.gatherer.util.Utility;
+import org.greenstone.gatherer.util.ZipTools;
+
 
 /** The <strong>GShell</strong> is reponsible for running a separately threaded process in the command shell. This is necessary for executing the Perl Scripts and also for other system related funcitonality.
@@ -240,5 +242,5 @@
 		if(Gatherer.c_man.getCollection().getFilesChanged() || !Gatherer.g_man.create_pane.isIncremental()) {
 		    // zip up import folder, but exclude metadata
-		    Utility.zipup(collect_directory_path, col_name, "import", this, "", ".*metadata\\.xml");
+		    ZipTools.zipup(collect_directory_path, col_name, "import", this, "", ".*metadata\\.xml");
 
 		    if(hasSignalledStop()) { return; }
@@ -251,5 +253,5 @@
 		if(Gatherer.c_man.getCollection().getMetadataChanged() || !Gatherer.g_man.create_pane.isIncremental()) {
 		    // zip up metadata from import folder
-		    Utility.zipup(collect_directory_path, col_name, "import", this, ".*metadata\\.xml", "");
+		    ZipTools.zipup(collect_directory_path, col_name, "import", this, ".*metadata\\.xml", "");
 
 		    if(hasSignalledStop()) { return; }
@@ -262,5 +264,5 @@
 		if(hasSignalledStop()) { return; }
 		// upload etc folder to server (need collect.cfg and any hfiles)
-		Utility.zipup(collect_directory_path, col_name, "etc", this, "", "");
+		ZipTools.zipup(collect_directory_path, col_name, "etc", this, "", "");
 
 		if(hasSignalledStop()) { return; }
@@ -272,5 +274,5 @@
 		    // upload images/ directory to server
 		    if(hasSignalledStop()) { return; }
-		    Utility.zipup(collect_directory_path, col_name, "images", this, "", "");
+		    ZipTools.zipup(collect_directory_path, col_name, "images", this, "", "");
 
 		    if(hasSignalledStop()) { return; }
@@ -554,5 +556,5 @@
 		    RemoteGreenstoneServer.download_url_zip(col_name, ".", this, "", "");
 		    if (!hasSignalledStop()) {
-			Utility.unzip(Gatherer.getCollectDirectoryPath(), col_name);
+			ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
 		    }
 		}
@@ -585,5 +587,5 @@
 			return;
 		    }
-		    Utility.unzip(Gatherer.getCollectDirectoryPath(), col_name);
+		    ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
 		    
 		    if (progress!=null) {
@@ -611,5 +613,5 @@
 		    RemoteGreenstoneServer.download_url_zip(col_name, "building", this, ".*build\\.cfg", "");
 		    if (!hasSignalledStop()) {
-			Utility.unzip(Gatherer.getCollectDirectoryPath(), col_name);
+			ZipTools.unzip(Gatherer.getCollectDirectoryPath(), col_name);
 		    }
 		    
@@ -654,5 +656,5 @@
 		    RemoteGreenstoneServer.download_url_zip(user_tmp_dir,cd_dir,this,"","");
 
-		    Utility.unzip(Configuration.gsdl_path, user_tmp_dir.substring(1));
+		    ZipTools.unzip(Configuration.gsdl_path, user_tmp_dir.substring(1));
 
 		    if (progress!=null) {
Index: trunk/gli/src/org/greenstone/gatherer/util/Utility.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/util/Utility.java	(revision 10250)
@@ -42,5 +42,4 @@
 import java.net.*;
 import java.util.*;
-import java.util.zip.*;
 // Don't even think about adding import javax.swing.* here!
 // The functions in this class should not use any graphical classes. Put your function somewhere else buster!
@@ -443,402 +442,4 @@
 
 
-    /** 
-     * Method which unzips a given metadata resoure.
-     * @param jar_zip_fname The name of the jar file as a <strong>String</strong>.
-     * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
-     * @see JarTools.extractFromJar(String, String, boolean)
-     */
-    static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
-
-	File file = null;
-	if (!dst_dir.endsWith(File.separator)) {
-	    dst_dir += File.separator;
-	}
-
-	JarTools.extractFromJar(jar_zip_fname,dst_dir,true);
-
-	String zip_ofname = dst_dir + jar_zip_fname;
-	File zip_file = new File(zip_ofname);
-
-	try {
-	    ZipFile zipfile = new ZipFile(zip_file);
-	    
-	    Enumeration e = zipfile.entries(); 
-	    while (e.hasMoreElements()) {
-		ZipEntry zipentry = (ZipEntry) e.nextElement();
-		String zentryname = dst_dir + zipentry.getName();
-		DebugStream.println("    Unzipping: " + zentryname);
-
-		if (zipentry.isDirectory()) {
-		    // Create named directory, if it doesn't already exist
-		    File zip_entry_file = new File(zentryname);
-		    if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
-			System.err.println("Error: unable to create directory " + zip_entry_file);
-		    }
-		}
-		else {
-		    // Write out file to disk
-
-		    // set up input stream
-		    InputStream zis = zipfile.getInputStream(zipentry); 
-		    BufferedInputStream bzis = new BufferedInputStream(zis); 
-		    DataInputStream dbzis = new DataInputStream(bzis);
-		    
-		    // set up output stream
-		    FileOutputStream fzos = new FileOutputStream(zentryname);
-		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
-		    
-		    byte[] buf = new byte[1024];
-		    int len;
-		    while ((len = dbzis.read(buf)) >= 0) {
-			bfzos.write(buf,0,len);
-		    }
-		    
-		    dbzis.close();
-		    bfzos.close();
-		}
-	    }
-	} 
-	catch (ZipException error) {
-	    System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
-	    DebugStream.printStackTrace(error);
-	}
-
-	catch (Exception error) {
-	    error.printStackTrace();
-	}
-    }
-    
-
-    static protected String unixStylePath(String path)
-    {
-	String unix_path = path.replace('\\','/');
-	return unix_path;
-    }
-
-    /**
-     * Method to handle zipping up of a file (not a directory).
-     * Called by {@link zipup(String, String, String, GShell, String, String)} and {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)}
-     *
-     * @param zos the zip output stream, as a <strong>ZipOutputStream</strong>
-     * @param file_path the <strong>String</strong> containing the path to the file/directory tozip up
-     * @param prefix_strip the <strong>int</strong> used to substring the file_path
-     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
-     *               This is null if GShell is not the calling object.
-     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
-     *                    There is a special case of ".*doc.xml", where the doc.xml files will be parsed to only include their metadata.
-     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
-     * @return boolean - true if the zip was created successfully(?).
-     * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
-     * @see zipup(String, String, String, GShell, String, String)
-     */
-    static protected boolean zipFunc(ZipOutputStream zos, String file_path, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr) 
-    {
-	String new_file_path = file_path;
-
-	if((reject_expr != "") && (file_path.matches(reject_expr))) {
-	    // matches reject expression
-	    //DebugStream.println("File \'" + file_path + "\' matches the reject expression \'" + reject_expr + "\'");
-	    return encountered_file;
-	}
-
-	if ((accept_expr != "") && (!file_path.matches(accept_expr))) {
-	    // does not match accept expression
-	    //DebugStream.println("File \'" + file_path + "\' doesn't match accept expression \'" + accept_expr + "\'");
-	    return encountered_file;
-	}
-
-	//Special case: we only want the metadata. Parse the xml files.
-	if(accept_expr.compareTo(".*doc.xml") == 0) {
-	    DebugStream.println("Only want to get metadata");
-	    Document old_document = XMLTools.parseXMLFile(new File(file_path));
-	    NodeList content = old_document.getElementsByTagName("Content");
-
-	    try {
-		for(int i=content.getLength()-1; i >= 0; i--) {
-		    //Remove all content - just leave the metadata.
-		    content.item(i).getParentNode().removeChild(content.item(i));
-		}
-	    }
-	    catch (Exception ex) {
-		ex.printStackTrace();
-	    }
-
-	    new_file_path = file_path.substring(0, file_path.lastIndexOf(File.separator) + 1) + "new.xml";
-	    //Is there any better way than writing out as a new file, then reading back in??
-	    XMLTools.writeXMLFile(new File(new_file_path), old_document);
-	}
-
-	// Using try is required because of file io.
-	try {
-	    // Exit if pressed cancel.
-	    if (source != null && source.hasSignalledStop()) {
-		return false;
-	    }
-
-	    // Create a Zip Entry and put it into the archive (no data yet).
-
-	    // Strip off col_dir prefix
-	    String zip_path = file_path.substring(prefix_strip);
-	    // Zip files use '/' for directory separator
-	    String unix_style_path = unixStylePath(zip_path);
-
-	    ZipEntry fileEntry = new ZipEntry(unix_style_path);
-	    zos.putNextEntry(fileEntry);
-
-	    // Create a file input stream and a buffered input stream.
-	    FileInputStream fis = new FileInputStream(new_file_path);
-	    BufferedInputStream bis = new BufferedInputStream(fis);
-	    
-	    // Create a byte array object named data and declare byte count variable.
-	    byte[] data = new byte[1024];
-	    int byteCount;
-	    // Create a loop that reads from the buffered input stream and writes
-	    // to the zip output stream until the bis has been entirely read.
-	    while ((byteCount = bis.read(data, 0, 1024)) > -1) {
-		//Check for cancell
-		if(source != null) {
-		    if(source.hasSignalledStop()) {
-			break;
-		    }
-		}
-		zos.write(data, 0, byteCount);
-	    }
-	    encountered_file = true;
-	} 
-	catch (IOException e) {
-	    e.printStackTrace();
-	}
-	
-	DebugStream.println("Zipping up: " + file_path);
-	return encountered_file;
-    }
-
-    /**
-     * Method to handle ziping up of a directory. This is called by {@link zipup(String, String, String, GShell, String, String)}
-     *
-     * @param zos the <strong>ZipOutputStream</strong> to output to.
-     * @param dir_name the directory name to zip, as a <strong>String</strong>
-     * @param prefix_strip the <strong>int</strong> used to substring the file_path
-     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
-     *               This is null if GShell is not the calling object.
-     * @param encountered_file ??What's this??
-     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
-     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
-     *
-     * @see zipup(String, String, String, GShell, String, String)
-     * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
-     */
-    static protected boolean dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr) 
-    {
-	File dirObj = new File(dir_name);
-
-	if (dirObj.exists() == true) {
-	    if (dirObj.isDirectory() == true) {
-		// Create an array of File objects, one for each file or directory in dirObj.
-		File [] fileList = dirObj.listFiles();
-		
-		// Loop through File array and display.
-		for (int i = 0; i < fileList.length; i++) {
-		    if(source != null && source.hasSignalledStop()) { break; }
-		    File file = fileList[i];
-		    if (file.isDirectory()) {
-			String dir_path = file.getPath();
-			String zip_path = dir_path.substring(prefix_strip);
-			// Zip files use '/' for directory separator
-			String unix_style_path 
-			    = unixStylePath(zip_path+File.separator);
-			ZipEntry dirEntry = new ZipEntry(unix_style_path);
-
-			try {
-			    zos.putNextEntry(dirEntry);
-			} 
-			catch (IOException e) {
-			    e.printStackTrace();
-			}
-
-			encountered_file = dirFunc(zos, dir_path, prefix_strip, source, encountered_file, accept_expr, reject_expr);
-		    } else if (file.isFile()) {
-			// Call the zipFunc function
-			String file_path = fileList[i].getPath();
-			encountered_file = zipFunc(zos,file_path,prefix_strip, source, encountered_file, accept_expr, reject_expr);
-		    }
-		}
-	    } 
-	    else { 
-		System.err.println (dir_name+" is not a directory."); 
-	    }
-	} 
-	else { 
-	    System.err.println ("Directory "+dir_name+" does not exist."); 
-	}
-	return encountered_file;
-    }
-    
-    /**
-     * Method to zip up a given file or directory associated with a particular collection.
-     * This method mainly called from {@link GShell}, with a few exceptions. The zip files produced are used
-     * to pass files (new files to add, metadata, etc) between the GLI applet and the Greenstone server.
-     * The actual zipping of files and directories is handled by {@link zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) and
-     * {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)} respectfully.
-     *
-     * @param col_dir the path to the collect directory, as a <strong>String</strong>
-     * @param col_name the collection name, as as <strong>String</strong>
-     * @param dir_or_file the directory or file within the collection to zip up, as a <strong>String</strong>
-     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
-     *               This is null if GShell is not the calling object.
-     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
-     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
-     *
-     * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
-     * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
-     */
-    static public boolean zipup(String col_dir, String col_name, String dir_or_file, GShell source, String accept_expr, String reject_expr)
-    {
-	if (!col_dir.endsWith(File.separator)) {
-	    col_dir += File.separator;
-	}
-
-	int prefix_strip = col_dir.length();
-	boolean encountered_file = false;
-
-	String zip_fname = col_dir + col_name + ".zip";
-	String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
-	File zip_dof = new File(zip_dir_or_file);
-
-	try {
-	    FileOutputStream fos = new FileOutputStream(zip_fname);
-	    ZipOutputStream zos = new ZipOutputStream(fos);
-	    
-	    if (zip_dof.exists()) {
-		if (zip_dof.isDirectory()) {
-		    String zip_dir = zip_dir_or_file;
-		    encountered_file = dirFunc(zos, zip_dir, prefix_strip, source, encountered_file, accept_expr, reject_expr);
-		}
-		else {
-		    String zip_full_file = zip_dir_or_file; 
-		    String zip_path = zip_full_file.substring(prefix_strip);
-
-		    for (int i=1; i<zip_path.length(); i++) {
-			String ch = String.valueOf(zip_path.charAt(i));
-
-			if (ch.equals(File.separator)) {
-			    String dir_path = zip_path.substring(0,i);
-			    // Zip files use '/' for directory separator
-			    String unix_style_path 
-				= unixStylePath(dir_path+File.separator);
-			    ZipEntry dirEntry = new ZipEntry(unix_style_path);
-			    zos.putNextEntry(dirEntry);
-			}
-		    }
-		    encountered_file = zipFunc(zos, zip_full_file, prefix_strip, source, encountered_file, accept_expr, reject_expr);
-		}
-	    }
-	    else {
-		System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
-	    }
-	    
-	    // Close the file output streams for both the file and the zip.
-	    zos.flush();
-	    zos.close();
-	    fos.close();
-	} 
-	catch (IOException exception) {
-	    DebugStream.printStackTrace(exception);
-	    return false;
-	}
-	return encountered_file;
-    } 
-    
-    /**
-     * Method to unzip a zip file associated with a particular collection.
-     * The location and name of the zip file should be derrived from the collection. Please see below for details.
-     *
-     * @param col_dir the path to the collection directory, as a <strong>String</strong>. This is where the zip file should be located.
-     * @param col_name the name of the collection, as a <strong>String</strong>. This should be the name of the zip file (with a  .zip extension).
-     */
-    static public void unzip(String col_dir, String col_name)
-    {
-	if (!col_dir.endsWith(File.separator)) {
-	    col_dir += File.separator;
-	}
-
-	String zip_fname = col_dir + col_name + ".zip";
-	// int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
-	int zip_mode = ZipFile.OPEN_READ; 
-
-	try {
-	    File cfile = new File(zip_fname);
-	    ZipFile zipfile = new ZipFile(cfile, zip_mode);
-	    
-	    Enumeration e = zipfile.entries(); 
-	    while (e.hasMoreElements()) {
-		ZipEntry zipentry = (ZipEntry) e.nextElement();
-		String zentryname = col_dir + zipentry.getName();
-		File zfile = new File(zentryname);
-		DebugStream.println("    Unzipping: " + zentryname);
-
-		if (zipentry.isDirectory()) {
-		    // Create named directory, if it doesn't already exist
-		    if (!zfile.exists() && !zfile.mkdirs()) {
-			System.err.println("Error: unable to create directory " + zfile);
-		    }
-		}
-		else {
-		    // Write out file to disk
-
-		    //Make sure it's parent directory exists.
-		    File dir = new File(zfile.getParent());
-		    dir.mkdirs();
-
-		    // set up input stream
-		    InputStream zis = zipfile.getInputStream(zipentry); 
-		    BufferedInputStream bzis = new BufferedInputStream(zis); 
-		    DataInputStream dbzis = new DataInputStream(bzis);
-		    
-		    // set up output stream
-		    FileOutputStream fzos = new FileOutputStream(zentryname);
-		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
-		    
-		    byte[] buf = new byte[1024];
-		    int len;
-		    while ((len = dbzis.read(buf)) >= 0) {
-			bfzos.write(buf,0,len);
-		    }
-		    
-		    dbzis.close();
-		    bzis.close();
-		    zis.close();
-
-		    bfzos.close();
-		    fzos.close();
-		}
-	    }
-
-	    zipfile.close();
-
-	    // delete zip file
-	    boolean file_deleted = cfile.delete();
-	    if (file_deleted) {
-		System.err.println("Zip file " + cfile.toString() + " deleted");
-	    }
-	    else {
-		System.err.println("Zip file " + cfile.toString() + " NOT deleted");
-	    }
-
-
-	} 
-	catch (ZipException error) {
-	    System.err.println("Error: Unable to open '"+zip_fname+"'");
-	    System.err.println("This maybe caused by the zip file being empty.");
-	    DebugStream.printStackTrace(error);
-	}
-
-	catch (Exception error) {
-	    error.printStackTrace();
-	}
-    }
-
-
     static public String getSitesDir(String gsdl3_path) {
 	return gsdl3_path + File.separator + "web"
Index: trunk/gli/src/org/greenstone/gatherer/util/ZipTools.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/util/ZipTools.java	(revision 10250)
+++ trunk/gli/src/org/greenstone/gatherer/util/ZipTools.java	(revision 10250)
@@ -0,0 +1,437 @@
+/**
+ *############################################################################
+ * A component of the Greenstone Librarian Interface, part of the Greenstone
+ * digital library suite from the New Zealand Digital Library Project at the
+ * University of Waikato, New Zealand.
+ *
+ * Author: David Bainbridge, NZDL Project, University of Waikato, NZ
+ *
+ * Copyright (C) 2005 New Zealand Digital Library Project
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *############################################################################
+ */
+
+package org.greenstone.gatherer.util;
+
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.greenstone.gatherer.DebugStream;
+import org.greenstone.gatherer.shell.GShell;
+import org.w3c.dom.*;
+
+
+public class ZipTools
+{
+    static protected String unixStylePath(String path)
+    {
+	String unix_path = path.replace('\\','/');
+	return unix_path;
+    }
+
+
+    /**
+     * Method to handle zipping up of a file (not a directory).
+     * Called by {@link zipup(String, String, String, GShell, String, String)} and {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)}
+     *
+     * @param zos the zip output stream, as a <strong>ZipOutputStream</strong>
+     * @param file_path the <strong>String</strong> containing the path to the file/directory tozip up
+     * @param prefix_strip the <strong>int</strong> used to substring the file_path
+     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
+     *               This is null if GShell is not the calling object.
+     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
+     *                    There is a special case of ".*doc.xml", where the doc.xml files will be parsed to only include their metadata.
+     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
+     * @return boolean - true if the zip was created successfully(?).
+     * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
+     * @see zipup(String, String, String, GShell, String, String)
+     */
+    static protected boolean zipFunc(ZipOutputStream zos, String file_path, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr) 
+    {
+	String new_file_path = file_path;
+
+	if((reject_expr != "") && (file_path.matches(reject_expr))) {
+	    // matches reject expression
+	    //DebugStream.println("File \'" + file_path + "\' matches the reject expression \'" + reject_expr + "\'");
+	    return encountered_file;
+	}
+
+	if ((accept_expr != "") && (!file_path.matches(accept_expr))) {
+	    // does not match accept expression
+	    //DebugStream.println("File \'" + file_path + "\' doesn't match accept expression \'" + accept_expr + "\'");
+	    return encountered_file;
+	}
+
+	//Special case: we only want the metadata. Parse the xml files.
+	if(accept_expr.compareTo(".*doc.xml") == 0) {
+	    DebugStream.println("Only want to get metadata");
+	    Document old_document = XMLTools.parseXMLFile(new File(file_path));
+	    NodeList content = old_document.getElementsByTagName("Content");
+
+	    try {
+		for(int i=content.getLength()-1; i >= 0; i--) {
+		    //Remove all content - just leave the metadata.
+		    content.item(i).getParentNode().removeChild(content.item(i));
+		}
+	    }
+	    catch (Exception ex) {
+		ex.printStackTrace();
+	    }
+
+	    new_file_path = file_path.substring(0, file_path.lastIndexOf(File.separator) + 1) + "new.xml";
+	    //Is there any better way than writing out as a new file, then reading back in??
+	    XMLTools.writeXMLFile(new File(new_file_path), old_document);
+	}
+
+	// Using try is required because of file io.
+	try {
+	    // Exit if pressed cancel.
+	    if (source != null && source.hasSignalledStop()) {
+		return false;
+	    }
+
+	    // Create a Zip Entry and put it into the archive (no data yet).
+
+	    // Strip off col_dir prefix
+	    String zip_path = file_path.substring(prefix_strip);
+	    // Zip files use '/' for directory separator
+	    String unix_style_path = unixStylePath(zip_path);
+
+	    ZipEntry fileEntry = new ZipEntry(unix_style_path);
+	    zos.putNextEntry(fileEntry);
+
+	    // Create a file input stream and a buffered input stream.
+	    FileInputStream fis = new FileInputStream(new_file_path);
+	    BufferedInputStream bis = new BufferedInputStream(fis);
+	    
+	    // Create a byte array object named data and declare byte count variable.
+	    byte[] data = new byte[1024];
+	    int byteCount;
+	    // Create a loop that reads from the buffered input stream and writes
+	    // to the zip output stream until the bis has been entirely read.
+	    while ((byteCount = bis.read(data, 0, 1024)) > -1) {
+		//Check for cancell
+		if(source != null) {
+		    if(source.hasSignalledStop()) {
+			break;
+		    }
+		}
+		zos.write(data, 0, byteCount);
+	    }
+	    encountered_file = true;
+	} 
+	catch (IOException e) {
+	    e.printStackTrace();
+	}
+	
+	DebugStream.println("Zipping up: " + file_path);
+	return encountered_file;
+    }
+
+    /**
+     * Method to handle ziping up of a directory. This is called by {@link zipup(String, String, String, GShell, String, String)}
+     *
+     * @param zos the <strong>ZipOutputStream</strong> to output to.
+     * @param dir_name the directory name to zip, as a <strong>String</strong>
+     * @param prefix_strip the <strong>int</strong> used to substring the file_path
+     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
+     *               This is null if GShell is not the calling object.
+     * @param encountered_file ??What's this??
+     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
+     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
+     *
+     * @see zipup(String, String, String, GShell, String, String)
+     * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
+     */
+    static protected boolean dirFunc (ZipOutputStream zos, String dir_name, int prefix_strip, GShell source, boolean encountered_file, String accept_expr, String reject_expr) 
+    {
+	File dirObj = new File(dir_name);
+
+	if (dirObj.exists() == true) {
+	    if (dirObj.isDirectory() == true) {
+		// Create an array of File objects, one for each file or directory in dirObj.
+		File [] fileList = dirObj.listFiles();
+		
+		// Loop through File array and display.
+		for (int i = 0; i < fileList.length; i++) {
+		    if(source != null && source.hasSignalledStop()) { break; }
+		    File file = fileList[i];
+		    if (file.isDirectory()) {
+			String dir_path = file.getPath();
+			String zip_path = dir_path.substring(prefix_strip);
+			// Zip files use '/' for directory separator
+			String unix_style_path 
+			    = unixStylePath(zip_path+File.separator);
+			ZipEntry dirEntry = new ZipEntry(unix_style_path);
+
+			try {
+			    zos.putNextEntry(dirEntry);
+			} 
+			catch (IOException e) {
+			    e.printStackTrace();
+			}
+
+			encountered_file = dirFunc(zos, dir_path, prefix_strip, source, encountered_file, accept_expr, reject_expr);
+		    } else if (file.isFile()) {
+			// Call the zipFunc function
+			String file_path = fileList[i].getPath();
+			encountered_file = zipFunc(zos,file_path,prefix_strip, source, encountered_file, accept_expr, reject_expr);
+		    }
+		}
+	    } 
+	    else { 
+		System.err.println (dir_name+" is not a directory."); 
+	    }
+	} 
+	else { 
+	    System.err.println ("Directory "+dir_name+" does not exist."); 
+	}
+	return encountered_file;
+    }
+    
+    /**
+     * Method to zip up a given file or directory associated with a particular collection.
+     * This method mainly called from {@link GShell}, with a few exceptions. The zip files produced are used
+     * to pass files (new files to add, metadata, etc) between the GLI applet and the Greenstone server.
+     * The actual zipping of files and directories is handled by {@link zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) and
+     * {@link dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String)} respectfully.
+     *
+     * @param col_dir the path to the collect directory, as a <strong>String</strong>
+     * @param col_name the collection name, as as <strong>String</strong>
+     * @param dir_or_file the directory or file within the collection to zip up, as a <strong>String</strong>
+     * @param source the <strong>GShell</strong> object that is calling this method, so that we can check to see if the process has been cancelled.
+     *               This is null if GShell is not the calling object.
+     * @param accept_expr a <strong>String</strong> containing a regular expression of files to include in the archive. All other files will be excluded.
+     * @param reject_expr a <strong>String</strong> containing a regular expression of files not to include in the archive.
+     *
+     * @see zipFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
+     * @see dirFunc(ZipOutputStream, String, int, GShell, boolean, String, String) 
+     */
+    static public boolean zipup(String col_dir, String col_name, String dir_or_file, GShell source, String accept_expr, String reject_expr)
+    {
+	if (!col_dir.endsWith(File.separator)) {
+	    col_dir += File.separator;
+	}
+
+	int prefix_strip = col_dir.length();
+	boolean encountered_file = false;
+
+	String zip_fname = col_dir + col_name + ".zip";
+	String zip_dir_or_file = col_dir + col_name + File.separator + dir_or_file;
+	File zip_dof = new File(zip_dir_or_file);
+
+	try {
+	    FileOutputStream fos = new FileOutputStream(zip_fname);
+	    ZipOutputStream zos = new ZipOutputStream(fos);
+	    
+	    if (zip_dof.exists()) {
+		if (zip_dof.isDirectory()) {
+		    String zip_dir = zip_dir_or_file;
+		    encountered_file = dirFunc(zos, zip_dir, prefix_strip, source, encountered_file, accept_expr, reject_expr);
+		}
+		else {
+		    String zip_full_file = zip_dir_or_file; 
+		    String zip_path = zip_full_file.substring(prefix_strip);
+
+		    for (int i=1; i<zip_path.length(); i++) {
+			String ch = String.valueOf(zip_path.charAt(i));
+
+			if (ch.equals(File.separator)) {
+			    String dir_path = zip_path.substring(0,i);
+			    // Zip files use '/' for directory separator
+			    String unix_style_path 
+				= unixStylePath(dir_path+File.separator);
+			    ZipEntry dirEntry = new ZipEntry(unix_style_path);
+			    zos.putNextEntry(dirEntry);
+			}
+		    }
+		    encountered_file = zipFunc(zos, zip_full_file, prefix_strip, source, encountered_file, accept_expr, reject_expr);
+		}
+	    }
+	    else {
+		System.err.println("Warning: " + zip_dir_or_file + " does not exist!");
+	    }
+	    
+	    // Close the file output streams for both the file and the zip.
+	    zos.flush();
+	    zos.close();
+	    fos.close();
+	} 
+	catch (IOException exception) {
+	    DebugStream.printStackTrace(exception);
+	    return false;
+	}
+	return encountered_file;
+    } 
+    
+    /**
+     * Method to unzip a zip file associated with a particular collection.
+     * The location and name of the zip file should be derrived from the collection. Please see below for details.
+     *
+     * @param col_dir the path to the collection directory, as a <strong>String</strong>. This is where the zip file should be located.
+     * @param col_name the name of the collection, as a <strong>String</strong>. This should be the name of the zip file (with a  .zip extension).
+     */
+    static public void unzip(String col_dir, String col_name)
+    {
+	if (!col_dir.endsWith(File.separator)) {
+	    col_dir += File.separator;
+	}
+
+	String zip_fname = col_dir + col_name + ".zip";
+	// int zip_mode = ZipFile.OPEN_READ | ZipFile.OPEN_DELETE;
+	int zip_mode = ZipFile.OPEN_READ; 
+
+	try {
+	    File cfile = new File(zip_fname);
+	    ZipFile zipfile = new ZipFile(cfile, zip_mode);
+	    
+	    Enumeration e = zipfile.entries(); 
+	    while (e.hasMoreElements()) {
+		ZipEntry zipentry = (ZipEntry) e.nextElement();
+		String zentryname = col_dir + zipentry.getName();
+		File zfile = new File(zentryname);
+		DebugStream.println("    Unzipping: " + zentryname);
+
+		if (zipentry.isDirectory()) {
+		    // Create named directory, if it doesn't already exist
+		    if (!zfile.exists() && !zfile.mkdirs()) {
+			System.err.println("Error: unable to create directory " + zfile);
+		    }
+		}
+		else {
+		    // Write out file to disk
+
+		    //Make sure it's parent directory exists.
+		    File dir = new File(zfile.getParent());
+		    dir.mkdirs();
+
+		    // set up input stream
+		    InputStream zis = zipfile.getInputStream(zipentry); 
+		    BufferedInputStream bzis = new BufferedInputStream(zis); 
+		    DataInputStream dbzis = new DataInputStream(bzis);
+		    
+		    // set up output stream
+		    FileOutputStream fzos = new FileOutputStream(zentryname);
+		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
+		    
+		    byte[] buf = new byte[1024];
+		    int len;
+		    while ((len = dbzis.read(buf)) >= 0) {
+			bfzos.write(buf,0,len);
+		    }
+		    
+		    dbzis.close();
+		    bzis.close();
+		    zis.close();
+
+		    bfzos.close();
+		    fzos.close();
+		}
+	    }
+
+	    zipfile.close();
+
+	    // delete zip file
+	    boolean file_deleted = cfile.delete();
+	    if (file_deleted) {
+		System.err.println("Zip file " + cfile.toString() + " deleted");
+	    }
+	    else {
+		System.err.println("Zip file " + cfile.toString() + " NOT deleted");
+	    }
+
+
+	} 
+	catch (ZipException error) {
+	    System.err.println("Error: Unable to open '"+zip_fname+"'");
+	    System.err.println("This maybe caused by the zip file being empty.");
+	    DebugStream.printStackTrace(error);
+	}
+
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+
+
+    /** 
+     * Method which unzips a given metadata resoure.
+     * @param jar_zip_fname The name of the jar file as a <strong>String</strong>.
+     * @param dst_dir The destination directory for unzipping, also as a <strong>String</strong>.
+     * @see JarTools.extractFromJar(String, String, boolean)
+     */
+    static public void unzipFromJar(String jar_zip_fname, String dst_dir) {
+
+	File file = null;
+	if (!dst_dir.endsWith(File.separator)) {
+	    dst_dir += File.separator;
+	}
+
+	JarTools.extractFromJar(jar_zip_fname,dst_dir,true);
+
+	String zip_ofname = dst_dir + jar_zip_fname;
+	File zip_file = new File(zip_ofname);
+
+	try {
+	    ZipFile zipfile = new ZipFile(zip_file);
+	    
+	    Enumeration e = zipfile.entries(); 
+	    while (e.hasMoreElements()) {
+		ZipEntry zipentry = (ZipEntry) e.nextElement();
+		String zentryname = dst_dir + zipentry.getName();
+		DebugStream.println("    Unzipping: " + zentryname);
+
+		if (zipentry.isDirectory()) {
+		    // Create named directory, if it doesn't already exist
+		    File zip_entry_file = new File(zentryname);
+		    if (!zip_entry_file.exists() && !zip_entry_file.mkdirs()) {
+			System.err.println("Error: unable to create directory " + zip_entry_file);
+		    }
+		}
+		else {
+		    // Write out file to disk
+
+		    // set up input stream
+		    InputStream zis = zipfile.getInputStream(zipentry); 
+		    BufferedInputStream bzis = new BufferedInputStream(zis); 
+		    DataInputStream dbzis = new DataInputStream(bzis);
+		    
+		    // set up output stream
+		    FileOutputStream fzos = new FileOutputStream(zentryname);
+		    BufferedOutputStream bfzos = new BufferedOutputStream(fzos);
+		    
+		    byte[] buf = new byte[1024];
+		    int len;
+		    while ((len = dbzis.read(buf)) >= 0) {
+			bfzos.write(buf,0,len);
+		    }
+		    
+		    dbzis.close();
+		    bfzos.close();
+		}
+	    }
+	} 
+	catch (ZipException error) {
+	    System.err.println("Error: Unable to open '"+zip_file.getAbsolutePath()+"'");
+	    DebugStream.printStackTrace(error);
+	}
+
+	catch (Exception error) {
+	    error.printStackTrace();
+	}
+    }
+}
Index: trunk/gli/src/org/greenstone/gatherer/util/Zipup.java
===================================================================
--- trunk/gli/src/org/greenstone/gatherer/util/Zipup.java	(revision 10249)
+++ trunk/gli/src/org/greenstone/gatherer/util/Zipup.java	(revision 10250)
@@ -42,5 +42,5 @@
 /**
  * Zip up a given directory of a given Greenstone collection.
- * The actual zipping code is contained in {@link Utility.zipup(String, String, String, GShell, String, String)}.
+ * The actual zipping code is contained in {@link ZipTools.zipup(String, String, String, GShell, String, String)}.
  * This class basically contains a main method that requires adequate arguments to call the zipup method.
  *
@@ -52,5 +52,5 @@
  * <br>[reject_expression], a regular expression of files to exclude from the archive. Optional.
  *
- * @see Utility.zipup(String, String, String, GShell, String, String)
+ * @see ZipTools.zipup(String, String, String, GShell, String, String)
  */
 public class Zipup {
@@ -91,5 +91,5 @@
 	}     
 
-	Utility.zipup(base_dir, collection, directory, null, accept_expr, reject_expr);
+	ZipTools.zipup(base_dir, collection, directory, null, accept_expr, reject_expr);
     }
 }
