Index: main/trunk/greenstone2/perllib/IncrementalBuildUtils.pm
===================================================================
--- main/trunk/greenstone2/perllib/IncrementalBuildUtils.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/IncrementalBuildUtils.pm	(revision 27303)
@@ -42,8 +42,25 @@
     die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
     die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/plugins");
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/classify");
+
+    # - ensure we only add perllib paths to INC if they weren't already there
+    # as otherwise we lose the ability to use order in INC as a guide for
+    # inheritence/overriding [jmt12]
+    my $gsdl_perllib_path = $ENV{'GSDLHOME'} . '/perllib';
+    my $found_path = 0;
+    foreach my $inc_path (@INC)
+    {
+      if ($inc_path eq $gsdl_perllib_path)
+      {
+        $found_path = 1;
+        last;
+      }
+    }
+    if (!$found_path)
+    {
+      unshift (@INC, $gsdl_perllib_path);
+      unshift (@INC, $gsdl_perllib_path . '/cpan');
+      unshift (@INC, $gsdl_perllib_path . '/plugins');
+      unshift (@INC, $gsdl_perllib_path . '/classify');
+    }
 }
 
@@ -65,5 +82,24 @@
   $path_separator = ";";
 }
-$ENV{'PATH'} = &util::filename_cat($ENV{'GSDLHOME'}, "bin", $ENV{'GSDLOS'}) . $path_separator . &util::filename_cat($ENV{'GSDLHOME'}, "bin", "script") . $path_separator.$ENV{'PATH'};
+# - once again we need to ensure we aren't duplicating paths on the environment
+# otherwise things like extension executables won't be correctly used in
+# preference to main Greenstone ones [jmt12]
+my @env_path = split($path_separator, $ENV{'PATH'});
+my $os_binary_path = &util::filename_cat($ENV{'GSDLHOME'}, 'bin', $ENV{'GSDLOS'});
+my $script_path = &util::filename_cat($ENV{'GSDLHOME'}, 'bin', 'script');
+my $found_os_bin = 0;
+foreach my $path (@env_path)
+{
+  if ($path eq $os_binary_path)
+  {
+    $found_os_bin = 1;
+    last;
+  }
+}
+if (!$found_os_bin)
+{
+  $ENV{'PATH'} = $os_binary_path . $path_separator . $script_path . $path_separator . $ENV{'PATH'};
+}
+
 
 # /**
Index: main/trunk/greenstone2/perllib/classify.pm
===================================================================
--- main/trunk/greenstone2/perllib/classify.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/classify.pm	(revision 27303)
@@ -29,4 +29,5 @@
 
 require util;
+use FileUtils;
 require AllList;
 
@@ -46,19 +47,41 @@
 
     # find the classifier
-    my $customclassname;
+    # - used to have hardcoded list of places to load classifier from. We
+    # should, instead, try loading from all of the perllib places on the
+    # library path, as that improves support for extensions. Special cases
+    # needed for collection specific and custom classifier. [jmt12]
+    my @possible_class_paths;
     if (defined($ENV{'GSDLCOLLECTION'}))
     {
-	$customclassname = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "custom", $ENV{'GSDLCOLLECTION'},
-                                              "perllib", "classify", "${classifier}.pm");
-    }
-    my $colclassname = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "classify", "${classifier}.pm");
-    my $mainclassname = &util::filename_cat($ENV{'GSDLHOME'}, "perllib", "classify", "${classifier}.pm");
-
-    if (defined($customclassname) && -e $customclassname) { require $customclassname; }
-    elsif (-e $colclassname) { require $colclassname; }
-    elsif (-e $mainclassname) { require $mainclassname; }
-    else { 
-	&gsprintf(STDERR, "{classify.could_not_find_classifier}\n", $classifier) && die "\n";
-    }
+      push(@possible_class_paths, &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, 'custom', $ENV{'GSDLCOLLECTION'}, 'perllib', 'classify', $classifier . '.pm'));
+    }
+    # (why does GSDLCOLLECTDIR get set to GSDLHOME for classinfo calls?)
+    if ($ENV{'GSDLCOLLECTDIR'} ne $ENV{'GSDLHOME'})
+    {
+      push(@possible_class_paths, &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, 'perllib', 'classify', $classifier . '.pm'));
+    }
+    foreach my $library_path (@INC)
+    {
+      # only interested in classify paths found in the library paths
+      if ($library_path =~ /classify$/)
+      {
+       push(@possible_class_paths, &FileUtils::filenameConcatenate($library_path, $classifier . '.pm'));
+      }
+    }
+    my $found_class = 0;
+    foreach my $possible_class_path (@possible_class_paths)
+    {
+      if (-e $possible_class_path)
+      {
+        require $possible_class_path;
+        $found_class = 1;
+        last;
+      }
+    }
+    if (!$found_class)
+    {
+      &gsprintf(STDERR, "{classify.could_not_find_classifier}\n", $classifier) && die "\n";
+    }
+
     my ($classobj);
     my $options = "-gsdlinfo";
@@ -74,7 +97,14 @@
     my $classify_number  = 1;
 
-     my $colclassdir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'},"perllib/classify");
-     unshift (@INC, $colclassdir);
-    
+    my $colclassdir = &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'},"perllib/classify");
+    # - ensure colclassdir doesn't already exist in INC before adding, other-
+    # wise we risk clobbering classifier inheritence implied by order of paths
+    # in INC [jmt12]
+    my $inc_paths = join(':',@INC);
+    if ($inc_paths !~ /$colclassdir/)
+    {
+      unshift (@INC, $colclassdir);
+    }
+
     foreach my $classifyoption (@$classify_list) {
 
@@ -84,14 +114,36 @@
 
 	# find the classifier
-        my $customclassname = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "custom", $ENV{'GSDLCOLLECTION'},
-                                                  "perllib", "classify", "${classname}.pm");
-        my $colclassname = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "perllib", "classify", "${classname}.pm");
-        my $mainclassname = &util::filename_cat($ENV{'GSDLHOME'}, "perllib", "classify", "${classname}.pm");
-
-	if (-e $customclassname) { require $customclassname; }
-	elsif (-e $colclassname) { require $colclassname; }
-	elsif (-e $mainclassname) { require $mainclassname; }
-	else { &gsprintf(STDERR, "{classify.could_not_find_classifier}\n", $classname) && die "\n";
-	       # die "ERROR - couldn't find classifier \"$classname\"\n";
+        # - replaced as explained in load_classifier_for_info() [jmt12]
+        my @possible_class_paths;
+        if (defined($ENV{'GSDLCOLLECTION'}))
+        {
+          push(@possible_class_paths, &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, 'custom', $ENV{'GSDLCOLLECTION'}, 'perllib', 'classify', $classname . '.pm'));
+        }
+        # (why does GSDLCOLLECTDIR get set to GSDLHOME for classinfo calls?)
+        if ($ENV{'GSDLCOLLECTDIR'} ne $ENV{'GSDLHOME'})
+        {
+          push(@possible_class_paths,&FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, 'perllib', 'classify', $classname . '.pm'));
+        }
+        foreach my $library_path (@INC)
+        {
+          # only interested in classify paths found in the library paths
+          if ($library_path =~ /classify$/)
+          {
+            push(@possible_class_paths, &FileUtils::filenameConcatenate($library_path, $classname . '.pm'));
+          }
+        }
+        my $found_class = 0;
+        foreach my $possible_class_path (@possible_class_paths)
+        {
+          if (-e $possible_class_path)
+          {
+            require $possible_class_path;
+            $found_class = 1;
+            last;
+          }
+        }
+        if (!$found_class)
+        {
+          &gsprintf(STDERR, "{classify.could_not_find_classifier}\n", $classname) && die "\n";
         }
 
Index: main/trunk/greenstone2/perllib/parse2.pm
===================================================================
--- main/trunk/greenstone2/perllib/parse2.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/parse2.pm	(revision 27303)
@@ -35,6 +35,23 @@
     die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
     die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+
+    # - ensure perllib paths don't already exist in INC before adding, other-
+    # wise we risk clobbering plugin/classifier inheritence implied by order
+    # of paths in INC [jmt12]
+    my $gsdl_perllib_path = $ENV{'GSDLHOME'} . '/perllib';
+    my $found_path = 0;
+    foreach my $inc_path (@INC)
+    {
+      if ($inc_path eq $gsdl_perllib_path)
+      {
+        $found_path = 1;
+        last;
+      }
+    }
+    if (!$found_path)
+    {
+      unshift (@INC, $gsdl_perllib_path);
+      unshift (@INC, $gsdl_perllib_path . '/cpan');
+    }
 }
 
Index: main/trunk/greenstone2/perllib/parse3.pm
===================================================================
--- main/trunk/greenstone2/perllib/parse3.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/parse3.pm	(revision 27303)
@@ -8,6 +8,23 @@
     die "GSDLHOME not set\n" unless defined $ENV{'GSDLHOME'};
     die "GSDLOS not set\n" unless defined $ENV{'GSDLOS'};
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib");
-    unshift (@INC, "$ENV{'GSDLHOME'}/perllib/cpan");
+
+    # - ensure perllib paths don't already exist in INC before adding, other-
+    # wise we risk clobbering plugin/classifier inheritence implied by order
+    # of paths in INC [jmt12]
+    my $gsdl_perllib_path = $ENV{'GSDLHOME'} . '/perllib';
+    my $found_path = 0;
+    foreach my $inc_path (@INC)
+    {
+      if ($inc_path eq $gsdl_perllib_path)
+      {
+        $found_path = 1;
+        last;
+      }
+    }
+    if (!$found_path)
+    {
+      unshift (@INC, $gsdl_perllib_path);
+      unshift (@INC, $gsdl_perllib_path . '/cpan');
+    }
 }
 
Index: main/trunk/greenstone2/perllib/plugin.pm
===================================================================
--- main/trunk/greenstone2/perllib/plugin.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/plugin.pm	(revision 27303)
@@ -32,4 +32,5 @@
 
 require util;
+use FileUtils;
 use gsprintf 'gsprintf';
 
@@ -84,5 +85,5 @@
     # pp_plugname shorthand for 'perllib' 'plugin' '$pluginname.pm' 
     my $pp_plugname 
-	= &util::filename_cat('perllib', 'plugins', "${pluginname}.pm");
+	= &FileUtils::filenameConcatenate('perllib', 'plugins', "${pluginname}.pm");
     my $collectdir = $ENV{'GSDLCOLLECTDIR'};
 
@@ -91,19 +92,19 @@
     {
 	my $customplugname 
-	    = &util::filename_cat($collectdir, "custom",$ENV{'GSDLCOLLECTION'},
+	    = &FileUtils::filenameConcatenate($collectdir, "custom",$ENV{'GSDLCOLLECTION'},
 				  $pp_plugname);
 	push(@check_list,$customplugname);
     }
 
-    my $colplugname = &util::filename_cat($collectdir, $pp_plugname);
+    my $colplugname = &FileUtils::filenameConcatenate($collectdir, $pp_plugname);
     push(@check_list,$colplugname);
 
     if (defined $ENV{'GSDLEXTS'}) {
 
-	my $ext_prefix = &util::filename_cat($ENV{'GSDLHOME'}, "ext");
+	my $ext_prefix = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "ext");
 
 	my @extensions = split(/:/,$ENV{'GSDLEXTS'});
 	foreach my $e (@extensions) {
-	    my $extplugname = &util::filename_cat($ext_prefix, $e, $pp_plugname);
+	    my $extplugname = &FileUtils::filenameConcatenate($ext_prefix, $e, $pp_plugname);
 	    push(@check_list,$extplugname);
 
@@ -112,9 +113,9 @@
     if (defined $ENV{'GSDL3EXTS'}) {
 
-	my $ext_prefix = &util::filename_cat($ENV{'GSDL3SRCHOME'}, "ext");
+	my $ext_prefix = &FileUtils::filenameConcatenate($ENV{'GSDL3SRCHOME'}, "ext");
 
 	my @extensions = split(/:/,$ENV{'GSDL3EXTS'});
 	foreach my $e (@extensions) {
-	    my $extplugname = &util::filename_cat($ext_prefix, $e, $pp_plugname);
+	    my $extplugname = &FileUtils::filenameConcatenate($ext_prefix, $e, $pp_plugname);
 	    push(@check_list,$extplugname);
 
@@ -123,5 +124,5 @@
 
 
-    my $mainplugname = &util::filename_cat($ENV{'GSDLHOME'}, $pp_plugname);
+    my $mainplugname = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, $pp_plugname);
     push(@check_list,$mainplugname);
 
@@ -130,8 +131,22 @@
 	if (-e $plugname) {
 	    # lets add perllib folder to INC
+          # check it isn't already there first [jmt12]
 	    my ($perllibfolder) = $plugname =~ /^(.*[\/\\]perllib)[\/\\]plugins/;
-	    if (-d $perllibfolder) {
+	    if (-d $perllibfolder)
+            {
+              my $found_perllibfolder = 0;
+              foreach my $path (@INC)
+              {
+                if ($path eq $perllibfolder)
+                {
+                  $found_perllibfolder = 1;
+                  last;
+                }
+              }
+              if (!$found_perllibfolder)
+              {
 		unshift (@INC, $perllibfolder);
-	    } 
+              }
+	    }
 	    require $plugname;
 	    $success=1;
@@ -171,8 +186,8 @@
     $failhandle = 'STDERR' unless defined $failhandle;
 
-    my $colperllibdir = &util::filename_cat($ENV{'GSDLCOLLECTDIR'},"perllib");
-    unshift (@INC, $colperllibdir);  
-    my $colplugindir = &util::filename_cat($colperllibdir,"plugins");
-     unshift (@INC, $colplugindir);  
+    # before pushing collection perl and plugin directories onto INC, test that
+    # they aren't already there [jmt12]
+    &util::augmentINC(&FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'},'perllib'));
+    &util::augmentINC(&FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'},'perllib','plugins'));
 
     map { $_ = "\"$_\""; } @$globaloptions;
@@ -270,5 +285,5 @@
     # the .kill file is a handy (if not very elegant) way of aborting 
     # an import.pl or buildcol.pl process
-    if (-e &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
+    if (-e &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
 	gsprintf($outhandle, "{plugin.kill_file}\n");
 	die "\n";
@@ -301,5 +316,5 @@
     # the .kill file is a handy (if not very elegant) way of aborting 
     # an import.pl or buildcol.pl process
-    if (-e &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
+    if (-e &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
 	gsprintf($outhandle, "{plugin.kill_file}\n");
 	die "\n";
@@ -352,5 +367,5 @@
     # the .kill file is a handy (if not very elegant) way of aborting 
     # an import.pl or buildcol.pl process
-    if (-e &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
+    if (-e &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'}, ".kill")) {
 	gsprintf($outhandle, "{plugin.kill_file}\n");
 	die "\n";
Index: main/trunk/greenstone2/perllib/util.pm
===================================================================
--- main/trunk/greenstone2/perllib/util.pm	(revision 27302)
+++ main/trunk/greenstone2/perllib/util.pm	(revision 27303)
@@ -35,163 +35,32 @@
 # $^X works better in some cases to return the path to perl used to launch the script,
 # but if launched with plain "perl" (no full-path), that will be just what it returns.
-use Config; 
+use Config;
+# New module for file related utility functions - intended as a
+# placeholder for an extension that allows a variety of different
+# filesystems (FTP, HTTP, SAMBA, WEBDav, HDFS etc)
+use FileUtils;
 
 # removes files (but not directories)
 sub rm {
-    my (@files) = @_;
-
-    my @filefiles = ();
-
-    # make sure the files we want to delete exist 
-    # and are regular files
-    foreach my $file (@files) {
-	if (!-e $file) {
-	    print STDERR "util::rm $file does not exist\n";
-	} elsif ((!-f $file) && (!-l $file)) {
-	    print STDERR "util::rm $file is not a regular (or symbolic) file\n";
-	} else {
-	    push (@filefiles, $file);
-	}
-    }
-    
-    # remove the files
-    my $numremoved = unlink @filefiles;
-
-    # check to make sure all of them were removed
-    if ($numremoved != scalar(@filefiles)) {
-	print STDERR "util::rm Not all files were removed\n";
-    }
-}
-
-# removes files (but not directories) - can rename this to the default
-# "rm" subroutine  when debugging the deletion of individual files.
-sub rm_debug {
-    my (@files) = @_;
-    my @filefiles = ();
-
-    # make sure the files we want to delete exist 
-    # and are regular files
-    foreach my $file (@files) {
-		if (!-e $file) {
-		    print STDERR "util::rm $file does not exist\n";
-		} elsif ((!-f $file) && (!-l $file)) {
-		    print STDERR "util::rm $file is not a regular (or symbolic) file\n";
-		} else { # debug message
-			unlink($file) or warn "Could not delete file $file: $!\n";
-		}
-    }
-}
-
+  warnings::warnif("deprecated", "util::rm() is deprecated, using FileUtils::removeFiles() instead");
+  return &FileUtils::removeFiles(@_);
+}
 
 # recursive removal
 sub filtered_rm_r {
-    my ($files,$file_accept_re,$file_reject_re) = @_;
-
-#   my ($cpackage,$cfilename,$cline,$csubr,$chas_args,$cwantarray) = caller(2);
-#   my ($lcfilename) = ($cfilename =~ m/([^\\\/]*)$/);
-#   print STDERR "** Calling method (2): $lcfilename:$cline $cpackage->$csubr\n";
-	
-    my @files_array = (ref $files eq "ARRAY") ? @$files : ($files);
-
-    # recursively remove the files
-    foreach my $file (@files_array) {
-	$file =~ s/[\/\\]+$//; # remove trailing slashes
-	
-	if (!-e $file) {
-	    print STDERR "util::filtered_rm_r $file does not exist\n";
-
-	} elsif ((-d $file) && (!-l $file)) { # don't recurse down symbolic link
-	    # get the contents of this directory
-	    if (!opendir (INDIR, $file)) {
-		print STDERR "util::filtered_rm_r could not open directory $file\n";
-	    } else {
-		my @filedir = grep (!/^\.\.?$/, readdir (INDIR));
-		closedir (INDIR);
-				
-		# remove all the files in this directory
-		map {$_="$file/$_";} @filedir;
-		&filtered_rm_r (\@filedir,$file_accept_re,$file_reject_re);
-
-		if (!defined $file_accept_re && !defined $file_reject_re) {
-		    # remove this directory
-		    if (!rmdir $file) {
-			print STDERR "util::filtered_rm_r couldn't remove directory $file\n";
-		    }
-		}
-	    }
-	} else {
-	    next if (defined $file_reject_re && ($file =~ m/$file_reject_re/));
-
-	    if ((!defined $file_accept_re) || ($file =~ m/$file_accept_re/)) {
-		# remove this file	
-		&rm ($file);
-	    }
-	}
-    }
-}
-
+  warnings::warnif("deprecated", "util::filtered_rm_r() is deprecated, using FileUtils::removeFilesFiltered() instead");
+  return &FileUtils::removeFilesFiltered(@_);
+}
 
 # recursive removal
 sub rm_r {
-    my (@files) = @_;
-    
-    # use the more general (but reterospectively written function
-    # filtered_rm_r function()
-
-    filtered_rm_r(\@files,undef,undef); # no accept or reject expressions
-}
-
-
-
+  warnings::warnif("deprecated", "util::rm_r() is deprecated, using FileUtils::recursiveRemoveFiles() instead");
+  return &FileUtils::removeFilesRecursive(@_);
+}
 
 # moves a file or a group of files
 sub mv {
-    my $dest = pop (@_);
-    my (@srcfiles) = @_;
-
-    # remove trailing slashes from source and destination files
-    $dest =~ s/[\\\/]+$//;
-    map {$_ =~ s/[\\\/]+$//;} @srcfiles;
-
-    # a few sanity checks
-    if (scalar (@srcfiles) == 0) {
-	print STDERR "util::mv no destination directory given\n";
-	return;
-    } elsif ((scalar (@srcfiles) > 1) && (!-d $dest)) {
-	print STDERR "util::mv if multiple source files are given the ".
-	    "destination must be a directory\n";
-	return;
-    }
-
-    # move the files
-    foreach my $file (@srcfiles) {
-	my $tempdest = $dest;
-	if (-d $tempdest) {
-	    my ($filename) = $file =~ /([^\\\/]+)$/;
-	    $tempdest .= "/$filename";
-	}
-	if (!-e $file) {
-	    print STDERR "util::mv $file does not exist\n";
-	} else {
-	    if(!rename ($file, $tempdest)) {
-		print STDERR "**** Failed to rename $file to $tempdest\n";
-		&File::Copy::copy($file, $tempdest);
-		&rm($file);
-	    } 
-	    elsif(-e $file) { # rename (partially) succeeded) but srcfile still exists after rename
-		#print STDERR "*** srcfile $file still exists after rename to $tempdest\n";
-		if(!-e $tempdest) {
-		    print STDERR "@@@@ ERROR: $tempdest does not exist\n";
-		}
-		# Sometimes the rename operation fails (as does File::Copy::move).
-		# This turns out to be because the files are hardlinked. 
-		# Need to do a copy-delete in this case, however, the copy step is not necessary: 
-		# the srcfile got renamed into tempdest, but srcfile itself still exists, delete it.
-		#&File::Copy::copy($file, $tempdest);
-
-		&rm($file);	    
-	    }
-	}
-    }
+  warnings::warnif("deprecated", "util::mv() is deprecated, using FileUtils::moveFiles() instead");
+  return &FileUtils::moveFiles(@_);
 }
 
@@ -201,92 +70,13 @@
 # but other files and folders in the target will continue to exist
 sub mv_dir_contents {
-	my ($src_dir, $dest_dir) = @_;
-	
-	# Obtain listing of all files within src_dir
-	# Note that readdir lists relative paths, as well as . and ..
-	opendir(DIR, "$src_dir");
-	my @files= readdir(DIR); 
-	close(DIR);
-	
-	my @full_path_files = ();
-	foreach my $file (@files) {	
-		# process all except . and ..
-		unless($file eq "." || $file eq "..") {
-			
-			my $dest_subdir = &filename_cat($dest_dir, $file); # $file is still a relative path
-		
-			# construct absolute paths
-			$file = &filename_cat($src_dir, $file); # $file is now an absolute path
-			
-			# Recurse on directories which have an equivalent in target dest_dir
-			# If $file is a directory that already exists in target $dest_dir, 
-			# then a simple move operation will fail (definitely on Windows).
-			if(-d $file && -d $dest_subdir) { 
-				#print STDERR "**** $file is a directory also existing in target, its contents to be copied to $dest_subdir\n";
-				&mv_dir_contents($file, $dest_subdir);
-				
-				# now all content is moved across, delete empty dir in source folder
-				if(&is_dir_empty($file)) {
-					if (!rmdir $file) {
-						print STDERR "ERROR. util::mv_dir_contents couldn't remove directory $file\n";
-					} 
-				} else { # error
-					print STDERR "ERROR. util::mv_dir_contents: subfolder $file still non-empty after moving contents to $dest_subdir\n";
-				}
-			} else { # process files and any directories that don't already exist with a simple move
-				push(@full_path_files, $file);
-			}			
-		}
-	}
-	
-	if(!&dir_exists($dest_dir)) { # create target toplevel folder or subfolders if they don't exist
-		&mk_dir($dest_dir);
-	}
-
-	#print STDERR "@@@@@ Copying files |".join(",", @full_path_files)."| to: $dest_dir\n";
-
-	if(@full_path_files) { # if non-empty, there's something to copy across
-		&mv(@full_path_files, $dest_dir);
-	}
-}
-
+  warnings::warnif("deprecated", "util::mv_dir_contents() is deprecated, using FileUtils::moveDirectoryContents() instead");
+  return &FileUtils::moveDirectoryContents(@_);
+}
 
 # copies a file or a group of files
 sub cp {
-    my $dest = pop (@_);
-    my (@srcfiles) = @_;
-
-    # remove trailing slashes from source and destination files
-    $dest =~ s/[\\\/]+$//;
-    map {$_ =~ s/[\\\/]+$//;} @srcfiles;
-
-    # a few sanity checks
-    if (scalar (@srcfiles) == 0) {
-	print STDERR "util::cp no destination directory given\n";
-	return;
-    } elsif ((scalar (@srcfiles) > 1) && (!-d $dest)) {
-	print STDERR "util::cp if multiple source files are given the ".
-	    "destination must be a directory\n";
-	return;
-    }
-
-    # copy the files
-    foreach my $file (@srcfiles) {
-	my $tempdest = $dest;
-	if (-d $tempdest) {
-	    my ($filename) = $file =~ /([^\\\/]+)$/;
-	    $tempdest .= "/$filename";
-	}
-	if (!-e $file) {
-	    print STDERR "util::cp $file does not exist\n";
-	} elsif (!-f $file) {
-	    print STDERR "util::cp $file is not a plain file\n";
-	} else {
-	    &File::Copy::copy ($file, $tempdest);
-	}
-    }
-}
-
-
+  warnings::warnif("deprecated", "util::cp() is deprecated, using FileUtils::copyFiles() instead");
+  return &FileUtils::copyFiles(@_);
+}
 
 # recursively copies a file or group of files
@@ -295,56 +85,8 @@
 # another use cp instead
 sub cp_r {
-    my $dest = pop (@_);
-    my (@srcfiles) = @_;
-
-    # a few sanity checks
-    if (scalar (@srcfiles) == 0) {
-	print STDERR "util::cp_r no destination directory given\n";
-	return;
-    } elsif (-f $dest) {
-	print STDERR "util::cp_r destination must be a directory\n";
-	return;
-    }
-    
-    # create destination directory if it doesn't exist already
-    if (! -d $dest) {
-	my $store_umask = umask(0002);
-	mkdir ($dest, 0777);
-	umask($store_umask);
-    } 
-
-    # copy the files
-    foreach my $file (@srcfiles) {
-
-	if (!-e $file) {
-	    print STDERR "util::cp_r $file does not exist\n";
-
-	} elsif (-d $file) {
-	    # make the new directory
-	    my ($filename) = $file =~ /([^\\\/]*)$/;
-	    $dest = &util::filename_cat ($dest, $filename);
-	    my $store_umask = umask(0002);
-	    mkdir ($dest, 0777);
-	    umask($store_umask);
-
-	    # get the contents of this directory
-	    if (!opendir (INDIR, $file)) {
-		print STDERR "util::cp_r could not open directory $file\n";
-	    } else {
-		my @filedir = readdir (INDIR);
-		closedir (INDIR);
-		foreach my $f (@filedir) {
-		    next if $f =~ /^\.\.?$/;
-		    # copy all the files in this directory
-		    my $ff = &util::filename_cat ($file, $f); 
-		    &cp_r ($ff, $dest);
-		}
-	    }
-
-	} else {
-	    &cp($file, $dest);
-	}
-    }
-}
+  warnings::warnif("deprecated", "util::cp_r() is deprecated, using FileUtils::copyFilesrecursive() instead");
+  return &FileUtils::copyFilesRecursive(@_);
+}
+
 # recursively copies a file or group of files
 # syntax: cp_r (sourcefiles, destination directory)
@@ -352,129 +94,17 @@
 # another use cp instead
 sub cp_r_nosvn {
-    my $dest = pop (@_);
-    my (@srcfiles) = @_;
-
-    # a few sanity checks
-    if (scalar (@srcfiles) == 0) {
-	print STDERR "util::cp_r no destination directory given\n";
-	return;
-    } elsif (-f $dest) {
-	print STDERR "util::cp_r destination must be a directory\n";
-	return;
-    }
-    
-    # create destination directory if it doesn't exist already
-    if (! -d $dest) {
-	my $store_umask = umask(0002);
-	mkdir ($dest, 0777);
-	umask($store_umask);
-    } 
-
-    # copy the files
-    foreach my $file (@srcfiles) {
-
-	if (!-e $file) {
-	    print STDERR "util::cp_r $file does not exist\n";
-
-	} elsif (-d $file) {
-	    # make the new directory
-	    my ($filename) = $file =~ /([^\\\/]*)$/;
-	    $dest = &util::filename_cat ($dest, $filename);
-	    my $store_umask = umask(0002);
-	    mkdir ($dest, 0777);
-	    umask($store_umask);
-
-	    # get the contents of this directory
-	    if (!opendir (INDIR, $file)) {
-		print STDERR "util::cp_r could not open directory $file\n";
-	    } else {
-		my @filedir = readdir (INDIR);
-		closedir (INDIR);
-		foreach my $f (@filedir) {
-		    next if $f =~ /^\.\.?$/;
-		    next if $f =~ /^\.svn$/;
-		    # copy all the files in this directory
-		    my $ff = &util::filename_cat ($file, $f); 
-		    &cp_r ($ff, $dest);
-		}
-	    }
-
-	} else {
-	    &cp($file, $dest);
-	}
-    }
+  warnings::warnif("deprecated", "util::cp_r_nosvn() is deprecated, using FileUtils::copyFilesRecursiveNoSVN() instead");
+  return &FileUtils::copyFilesRecursiveNoSVN(@_);
 }
 
 # copies a directory and its contents, excluding subdirectories, into a new directory
 sub cp_r_toplevel {
-    my $dest = pop (@_);
-    my (@srcfiles) = @_;
-
-    # a few sanity checks
-    if (scalar (@srcfiles) == 0) {
-	print STDERR "util::cp_r no destination directory given\n";
-	return;
-    } elsif (-f $dest) {
-	print STDERR "util::cp_r destination must be a directory\n";
-	return;
-    }
-    
-    # create destination directory if it doesn't exist already
-    if (! -d $dest) {
-	my $store_umask = umask(0002);
-	mkdir ($dest, 0777);
-	umask($store_umask);
-    } 
-
-    # copy the files
-    foreach my $file (@srcfiles) {
-
-	if (!-e $file) {
-	    print STDERR "util::cp_r $file does not exist\n";
-
-	} elsif (-d $file) {
-	    # make the new directory
-	    my ($filename) = $file =~ /([^\\\/]*)$/;
-	    $dest = &util::filename_cat ($dest, $filename);
-	    my $store_umask = umask(0002);
-	    mkdir ($dest, 0777);
-	    umask($store_umask);
-
-	    # get the contents of this directory
-	    if (!opendir (INDIR, $file)) {
-		print STDERR "util::cp_r could not open directory $file\n";
-	    } else {
-		my @filedir = readdir (INDIR);
-		closedir (INDIR);
-		foreach my $f (@filedir) {
-		    next if $f =~ /^\.\.?$/;
-		    
-		    # copy all the files in this directory, but not directories
-		    my $ff = &util::filename_cat ($file, $f); 
-		    if (-f $ff) {
-			&cp($ff, $dest);
-			#&cp_r ($ff, $dest);
-		    }
-		}
-	    }
-
-	} else {
-	    &cp($file, $dest);
-	}
-    }
+  warnings::warnif("deprecated", "util::cp_r_toplevel() is deprecated, using FileUtils::recursiveCopyTopLevel() instead");
+  return &FileUtils::recursiveCopyTopLevel(@_);
 }
 
 sub mk_dir {
-    my ($dir) = @_;
-
-    my $store_umask = umask(0002);
-    my $mkdir_ok = mkdir ($dir, 0777);
-    umask($store_umask);
-    
-    if (!$mkdir_ok) 
-    {
-	print STDERR "util::mk_dir could not create directory $dir\n";
-	return;
-    }
+  warnings::warnif("deprecated", "util::mk_dir() is deprecated, using FileUtils::makeDirectory() instead");
+  return &FileUtils::makeDirectory(@_);
 }
 
@@ -483,114 +113,18 @@
 # slightly faster (surprisingly) - Stefan.
 sub mk_all_dir {
-    my ($dir) = @_;
-
-    # use / for the directory separator, remove duplicate and
-    # trailing slashes
-    $dir=~s/[\\\/]+/\//g; 
-    $dir=~s/[\\\/]+$//;
-
-    # make sure the cache directory exists
-    my $dirsofar = "";
-    my $first = 1;
-    foreach my $dirname (split ("/", $dir)) {
-	$dirsofar .= "/" unless $first;
-	$first = 0;
-
-	$dirsofar .= $dirname;
-
-	next if $dirname =~ /^(|[a-z]:)$/i;
-	if (!-e $dirsofar)
-	    {
-		my $store_umask = umask(0002);
-		my $mkdir_ok = mkdir ($dirsofar, 0777);
-		umask($store_umask);
-		if (!$mkdir_ok)
-		{
-		    print STDERR "util::mk_all_dir could not create directory $dirsofar\n";
-		    return;
-		}
-	    }
-    }
+  warnings::warnif("deprecated", "util::mk_all_dir() is deprecated, using FileUtils::makeAllDirectories() instead");
+  return &FileUtils::makeAllDirectories(@_);
 }
 
 # make hard link to file if supported by OS, otherwise copy the file
 sub hard_link {
-    my ($src, $dest, $verbosity) = @_;
-
-    # remove trailing slashes from source and destination files
-    $src =~ s/[\\\/]+$//;
-    $dest =~ s/[\\\/]+$//;
-
-##    print STDERR "**** src = ", unicode::debug_unicode_string($src),"\n";
-    # a few sanity checks
-    if (-e $dest) {
-	# destination file already exists
-	return;
-    }
-    elsif (!-e $src) {
-	print STDERR "util::hard_link source file \"$src\" does not exist\n";
-	return 1;
-    }
-    elsif (-d $src) {
-	print STDERR "util::hard_link source \"$src\" is a directory\n";
-	return 1;
-    }
-
-    my $dest_dir = &File::Basename::dirname($dest);
-    mk_all_dir($dest_dir) if (!-e $dest_dir);
-
-
-	if (!link($src, $dest)) {
-	if ((!defined $verbosity) || ($verbosity>2)) {
-	    print STDERR "util::hard_link: unable to create hard link. ";
-	    print STDERR " Copying file: $src -> $dest\n";
-	}
-	&File::Copy::copy ($src, $dest);
-    }
-    return 0;
+  warnings::warnif("deprecated", "util::hard_link() is deprecated, using FileUtils::hardLink() instead");
+  return &FileUtils::hardLink(@_);
 }
 
 # make soft link to file if supported by OS, otherwise copy file
 sub soft_link {
-    my ($src, $dest, $ensure_paths_absolute) = @_;
-
-    # remove trailing slashes from source and destination files
-    $src =~ s/[\\\/]+$//;
-    $dest =~ s/[\\\/]+$//;
-
-    # Ensure file paths are absolute IF requested to do so 
-    # Soft_linking didn't work for relative paths
-    if(defined $ensure_paths_absolute && $ensure_paths_absolute) {
-	# We need to ensure that the src file is the absolute path 
-	# See http://perldoc.perl.org/File/Spec.html
-	if(!File::Spec->file_name_is_absolute( $src ))  { # it's relative
-	    $src = File::Spec->rel2abs($src); # make absolute
-	}
-	# Might as well ensure that the destination file's absolute path is used
-	if(!File::Spec->file_name_is_absolute( $dest )) {
-	    $dest = File::Spec->rel2abs($dest); # make absolute
-	}
-    }
-
-    # a few sanity checks
-    if (!-e $src) {
-	print STDERR "util::soft_link source file $src does not exist\n";
-	return 0;
-    }
-
-    my $dest_dir = &File::Basename::dirname($dest);
-    mk_all_dir($dest_dir) if (!-e $dest_dir);
-
-    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
-		
-	# symlink not supported on windows
-	&File::Copy::copy ($src, $dest);
-
-    } elsif (!eval {symlink($src, $dest)}) {
-	print STDERR "util::soft_link: unable to create soft link.\n";
-	return 0;
-    }
-
-    return 1;
+  warnings::warnif("deprecated", "util::soft_link() is deprecated, using FileUtils::softLink() instead");
+  return &FileUtils::softLink(@_);
 }
 
@@ -625,50 +159,18 @@
 }
 
-
-sub fd_exists
-{
-    my $filename_full_path = shift @_;
-    my $test_op = shift @_ || "-e";
-
-    # By default tests for existance of file or directory (-e)
-    # Can be made more specific by providing second parameter (e.g. -f or -d)
-
-    my $exists = 0;
-
-    if ($ENV{'GSDLOS'} =~ m/^windows$/i) {
-	require Win32;
-	my $filename_short_path = Win32::GetShortPathName($filename_full_path);	
-	if (!defined $filename_short_path) {
-	    # Was probably still in UTF8 form (not what is needed on Windows)
-	    my $unicode_filename_full_path = eval "decode(\"utf8\",\$filename_full_path)";
-	    if (defined $unicode_filename_full_path) {
-		$filename_short_path = Win32::GetShortPathName($unicode_filename_full_path);
-	    }
-	}
-	$filename_full_path = $filename_short_path;
-    }
-
-    if (defined $filename_full_path) {
-	$exists = eval "($test_op \$filename_full_path)";
-    }
-
-    return $exists;
-}
-
-sub file_exists
-{
-    my ($filename_full_path) = @_;
-
-    return fd_exists($filename_full_path,"-f");
-}
-
-sub dir_exists
-{
-    my ($filename_full_path) = @_;
-
-    return fd_exists($filename_full_path,"-d");
-}
-
-
+sub fd_exists {
+  warnings::warnif("deprecated", "util::fd_exists() is deprecated, using FileUtils::fileTest() instead");
+  return &FileUtils::fileTest(@_);
+}
+
+sub file_exists {
+  warnings::warnif("deprecated", "util::file_exists() is deprecated, using FileUtils::fileExists() instead");
+  return &FileUtils::fileExists(@_);
+}
+
+sub dir_exists {
+  warnings::warnif("deprecated", "util::dir_exists() is deprecated, using FileUtils::directoryExists() instead");
+  return &FileUtils::directoryExists(@_);
+}
 
 # updates a copy of a directory in some other part of the filesystem
@@ -676,78 +178,6 @@
 # both $fromdir and $todir should be absolute paths
 sub cachedir {
-    my ($fromdir, $todir, $verbosity) = @_;
-    $verbosity = 1 unless defined $verbosity;
-
-    # use / for the directory separator, remove duplicate and
-    # trailing slashes
-    $fromdir=~s/[\\\/]+/\//g; 
-    $fromdir=~s/[\\\/]+$//;
-    $todir=~s/[\\\/]+/\//g; 
-    $todir=~s/[\\\/]+$//;
-
-    &mk_all_dir ($todir);
-
-    # get the directories in ascending order
-    if (!opendir (FROMDIR, $fromdir)) {
-	print STDERR "util::cachedir could not read directory $fromdir\n";
-	return;
-    }
-    my @fromdir = grep (!/^\.\.?$/, sort(readdir (FROMDIR)));
-    closedir (FROMDIR);
-
-    if (!opendir (TODIR, $todir)) {
-	print STDERR "util::cacedir could not read directory $todir\n";
-	return;
-    }
-    my @todir = grep (!/^\.\.?$/, sort(readdir (TODIR)));
-    closedir (TODIR);
-
-    my $fromi = 0;
-    my $toi = 0;
-		    
-    while ($fromi < scalar(@fromdir) || $toi < scalar(@todir)) {
-#	print "fromi: $fromi toi: $toi\n";
-
-	# see if we should delete a file/directory
-	# this should happen if the file/directory
-	# is not in the from list or if its a different
-	# size, or has an older timestamp
-	if ($toi < scalar(@todir)) {
-	    if (($fromi >= scalar(@fromdir)) ||
-		($todir[$toi] lt $fromdir[$fromi] || 
-		 ($todir[$toi] eq $fromdir[$fromi] && 
-		  &differentfiles("$fromdir/$fromdir[$fromi]","$todir/$todir[$toi]",
-				  $verbosity)))) {
-
-		# the files are different
-		&rm_r("$todir/$todir[$toi]");
-		splice(@todir, $toi, 1); # $toi stays the same
-
-	    } elsif ($todir[$toi] eq $fromdir[$fromi]) {
-		# the files are the same
-		# if it is a directory, check its contents
-		if (-d "$todir/$todir[$toi]") {
-		    &cachedir ("$fromdir/$fromdir[$fromi]",
-			       "$todir/$todir[$toi]", $verbosity);
-		}
-
-		$toi++;
-		$fromi++;
-		next;
-	    }
-	}
-  
-	# see if we should insert a file/directory
-	# we should insert a file/directory if there
-	# is no tofiles left or if the tofile does not exist
-	if ($fromi < scalar(@fromdir) && ($toi >= scalar(@todir) || 
-					  $todir[$toi] gt $fromdir[$fromi])) {
-	    &cp_r ("$fromdir/$fromdir[$fromi]", "$todir/$fromdir[$fromi]");
-	    splice (@todir, $toi, 0, $fromdir[$fromi]);
-
-	    $toi++;
-	    $fromi++;
-	}
-    }
+  warnings::warnif("deprecated", "util::cachedir() is deprecated, using FileUtils::synchronizeDirectories() instead");
+  return &FileUtils::synchronizeDirectories(@_);
 }
 
@@ -757,49 +187,6 @@
 # $file2 is allowed to be newer than $file1
 sub differentfiles {
-    my ($file1, $file2, $verbosity) = @_;
-    $verbosity = 1 unless defined $verbosity;
-
-    $file1 =~ s/\/+$//;
-    $file2 =~ s/\/+$//;
-    
-    my ($file1name) = $file1 =~ /\/([^\/]*)$/;
-    my ($file2name) = $file2 =~ /\/([^\/]*)$/;
-
-    return -1 unless (-e $file1 && -e $file2);
-    if ($file1name ne $file2name) {
-	print STDERR "filenames are not the same\n" if ($verbosity >= 2);
-	return 1;
-    }
-
-    my @file1stat = stat ($file1);
-    my @file2stat = stat ($file2);
-
-    if (-d $file1) {
-	if (! -d $file2) {
-	    print STDERR "one file is a directory\n" if ($verbosity >= 2);
-	    return 1;
-	}
-	return 0;
-    }
-
-    # both must be regular files
-    unless (-f $file1 && -f $file2) {
-	print STDERR "one file is not a regular file\n" if ($verbosity >= 2);
-	return 1;
-    }
-
-    # the size of the files must be the same
-    if ($file1stat[7] != $file2stat[7]) {
-	print STDERR "different sized files\n" if ($verbosity >= 2);
-	return 1;
-    }
-
-    # the second file cannot be older than the first
-    if ($file1stat[9] > $file2stat[9]) {
-	print STDERR "file is older\n" if ($verbosity >= 2);
-	return 1;
-    }
-
-    return 0;
+  warnings::warnif("deprecated", "util::differentfiles() is deprecated, using FileUtils::differentFiles() instead");
+  return &FileUtils::differentFiles(@_);
 }
 
@@ -822,14 +209,14 @@
     }
 
-    my $tmpdir = filename_cat($ENV{'GSDLHOME'}, "tmp");
+    my $tmpdir = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "tmp");
     &mk_all_dir ($tmpdir) unless -e $tmpdir;
 
     my $count = 1000;
     my $rand = int(rand $count);
-    my $full_tmp_filename = &filename_cat($tmpdir, "F$rand$opt_dot_file_ext");
+    my $full_tmp_filename = &FileUtils::filenameConcatenate($tmpdir, "F$rand$opt_dot_file_ext");
 
     while (-e $full_tmp_filename) {
 	$rand = int(rand $count);
-	$full_tmp_filename = &filename_cat($tmpdir, "F$rand$opt_dot_file_ext");
+	$full_tmp_filename = &FileUtils::filenameConcatenate($tmpdir, "F$rand$opt_dot_file_ext");
 	$count++;
     }
@@ -850,5 +237,5 @@
     }
 
-    $tmp_dirname = &util::filename_cat($tmp_dirname, "tmp");
+    $tmp_dirname = &FileUtils::filenameConcatenate($tmp_dirname, "tmp");
     &util::mk_dir($tmp_dirname) if (!-e $tmp_dirname);
 
@@ -856,5 +243,5 @@
     # if documents have the same name
     my $timestamp = time;
-    my $time_tmp_dirname = &util::filename_cat($tmp_dirname, $timestamp);
+    my $time_tmp_dirname = &FileUtils::filenameConcatenate($tmp_dirname, $timestamp);
     $tmp_dirname = $time_tmp_dirname;
     my $i = 1;
@@ -895,5 +282,5 @@
     }
     $output_ext= lc($output_ext);
-    my $tmp_filename = &util::filename_cat($tmp_dirname, "$tailname$output_ext");
+    my $tmp_filename = &FileUtils::filenameConcatenate($tmp_dirname, "$tailname$output_ext");
     
     return $tmp_filename;
@@ -902,5 +289,5 @@
 sub get_toplevel_tmp_dir
 {
-    return filename_cat($ENV{'GSDLHOME'}, "tmp");
+    return &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "tmp");
 }
 
@@ -940,29 +327,9 @@
 
 sub filename_cat {
-    my $first_file = shift(@_);
-    my (@filenames) = @_;
-
-#   Useful for debugging 
-#     -- might make sense to call caller(0) rather than (1)??
-#   my ($cpackage,$cfilename,$cline,$csubr,$chas_args,$cwantarray) = caller(1);
-#   print STDERR "Calling method: $cfilename:$cline $cpackage->$csubr\n";
-   
-    # If first_file is not null or empty, then add it back into the list
-    if (defined $first_file && $first_file =~ /\S/) {
-	unshift(@filenames, $first_file);
-    }
-
-    my $filename = join("/", @filenames);
-
-    # remove duplicate slashes and remove the last slash
-    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
-	$filename =~ s/[\\\/]+/\\/g;
-    } else {
-	$filename =~ s/[\/]+/\//g; 
-	# DB: want a filename abc\de.html to remain like this
-    }
-    $filename =~ s/[\\\/]$//;
-
-    return $filename;
+  # I've disabled this warning for now, as every Greenstone perl
+  # script seems to make use of this function and so you drown in a
+  # sea of deprecated warnings [jmt12]
+#  warnings::warnif("deprecated", "util::filename_cat() is deprecated, using FileUtils::filenameConcatenate() instead");
+  return &FileUtils::filenameConcatenate(@_);
 }
 
@@ -1074,5 +441,5 @@
     my $filename_full_path = $file;
     # add on directory if present
-    $filename_full_path = &util::filename_cat ($base_dir, $file) if $base_dir =~ /\S/;
+    $filename_full_path = &FileUtils::filenameConcatenate($base_dir, $file) if $base_dir =~ /\S/;
     
     my $filename_no_path = $file;
@@ -1106,6 +473,6 @@
     # use filename_cat to clean up trailing slashes and 
     # multiple slashes
-    $filename1 = filename_cat ($filename1);
-    $filename2 = filename_cat ($filename2);
+    $filename1 = &FileUtils::filenameConcatenate($filename1);
+    $filename2 = &FileUtils::filenameConcatenate($filename2);
 
     # filenames not case sensitive on windows
@@ -1237,5 +604,5 @@
     my ($base_dir,$file,$gli) = @_;
 
-    my $filename_full_path = &util::filename_cat($base_dir,$file);
+    my $filename_full_path = &FileUtils::filenameConcatenate($base_dir,$file);
 
     if ($ENV{'GSDLOS'} =~ m/^windows$/i) {
@@ -1327,12 +694,6 @@
 sub filename_is_absolute
 {
-    my ($filename) = @_;
-
-    if ($ENV{'GSDLOS'} =~ /^windows$/i) {
-	return ($filename =~ m/^(\w:)?\\/);
-    }
-    else {
-	return ($filename =~ m/^\//);
-    }
+  warnings::warnif("deprecated", "util::filename_is_absolute() is deprecated, using FileUtils::isFilenameAbsolute() instead");
+  return &FileUtils::isFilenameAbsolute(@_);
 }
 
@@ -1441,5 +802,5 @@
 
     if (!defined $collectdir || $collectdir eq "") {
-	$collectdir = &filename_cat ($ENV{'GSDLHOME'}, "collect");
+	$collectdir = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "collect");
     }
 
@@ -1462,5 +823,5 @@
     # are defined
     $ENV{'GSDLCOLLECTION'} = $collection;
-    $ENV{'GSDLCOLLECTDIR'} = &filename_cat ($collectdir, $collection);
+    $ENV{'GSDLCOLLECTDIR'} = &FileUtils::filenameConcatenate($collectdir, $collection);
 
     # make sure this collection exists
@@ -1487,5 +848,5 @@
     if (!defined $collectdir || $collectdir eq "") {
 	die "GSDL3HOME not set.\n" unless defined $ENV{'GSDL3HOME'};
-	$collectdir = &filename_cat ($ENV{'GSDL3HOME'}, "sites", $site, "collect");
+	$collectdir = &FileUtils::filenameConcatenate($ENV{'GSDL3HOME'}, "sites", $site, "collect");
     }
 
@@ -1523,5 +884,5 @@
 	if (defined $ENV{'GSDLCOLLECTDIR'} && $ENV{'GSDLCOLLECTDIR'} ne "") {
 	    my $test_collect_etc_filename 
-		= &util::filename_cat($ENV{'GSDLCOLLECTDIR'},"etc", $file);
+		= &FileUtils::filenameConcatenate($ENV{'GSDLCOLLECTDIR'},"etc", $file);
 	    
 	    if (-e $test_collect_etc_filename) {
@@ -1530,5 +891,5 @@
 	}
 	my $test_main_etc_filename 
-	    = &util::filename_cat($ENV{'GSDLHOME'},"etc", $file);
+	    = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'},"etc", $file);
 	if (-e $test_main_etc_filename) {
 	    push(@locations,$test_main_etc_filename);
@@ -1553,15 +914,7 @@
 # A method to check if a directory is empty (note that an empty directory still has non-zero size!!!) 
 # Code is from http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/436007700831
-sub is_dir_empty
-{
-    my ($path) = @_;
-    opendir DIR, $path;
-    while(my $entry = readdir DIR) {
-        next if($entry =~ /^\.\.?$/);
-        closedir DIR;
-        return 0;
-    }
-    closedir DIR;
-    return 1;
+sub is_dir_empty {
+  warnings::warnif("deprecated", "util::is_dir_empty() is deprecated, using FileUtils::isDirectoryEmpty() instead");
+  return &FileUtils::isDirectoryEmpty(@_);
 }
 
@@ -1669,9 +1022,9 @@
     if($ENV{'GSDL3SRCHOME'}) {
 	$defaultUrlprefix = "/greenstone3";
-	$configfile = &util::filename_cat($ENV{'GSDL3SRCHOME'}, "packages", "tomcat", "conf", "Catalina", "localhost", "greenstone3.xml");
+	$configfile = &FileUtils::filenameConcatenate($ENV{'GSDL3SRCHOME'}, "packages", "tomcat", "conf", "Catalina", "localhost", "greenstone3.xml");
 	push(@propertynames, qw/path\s*\=/);
     } else {
 	$defaultUrlprefix = "/greenstone";
-	$configfile = &util::filename_cat($ENV{'GSDLHOME'}, "cgi-bin", &os_dir(), "gsdlsite.cfg");
+	$configfile = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'}, "cgi-bin", &os_dir(), "gsdlsite.cfg");
 	push(@propertynames, (qw/\nhttpprefix/, qw/\ngwcgi/)); # inspect one property then the other 
     }
@@ -1777,5 +1130,5 @@
 	
 	if($ENV{'PERLPATH'}) {
-		# OR: # $perl_exec = &util::filename_cat($ENV{'PERLPATH'},"perl");
+		# OR: # $perl_exec = &FileUtils::filenameConcatenate($ENV{'PERLPATH'},"perl");
 		if($ENV{'GSDLOS'} =~ m/windows/) {
 			$perl_exec = "$ENV{'PERLPATH'}\\Perl.exe";
@@ -1804,7 +1157,7 @@
     if(defined $ENV{'GSDLHOME'}) { # should be, as this script would be launched from the cmd line 
 	                           # after running setup.bat or from GLI which also runs setup.bat
-	my $java_bin = &util::filename_cat($ENV{'GSDLHOME'},"packages","jre","bin");
+	my $java_bin = &FileUtils::filenameConcatenate($ENV{'GSDLHOME'},"packages","jre","bin");
 	if(-d $java_bin) {
-	    $java = &util::filename_cat($java_bin,"java");
+	    $java = &FileUtils::filenameConcatenate($java_bin,"java");
 	    $java = "\"".$java."\""; # quoted to preserve spaces in path
 	}
@@ -1844,5 +1197,5 @@
 	
 	if (defined $collect_dir && $collect_dir) { # ensure not empty string either
-	    return &util::filename_cat($collect_dir,$colgroup, $collection);
+	    return &FileUtils::filenameConcatenate($collect_dir,$colgroup, $collection);
 	}
 	elsif (defined($ENV{'GSDLCOLLECTDIR'})) {
@@ -1851,8 +1204,8 @@
 	else {
 	    if (defined $site) {
-			return &util::filename_cat($ENV{'GSDL3HOME'},"sites",$site,"collect",$colgroup, $collection);
+			return &FileUtils::filenameConcatenate($ENV{'GSDL3HOME'},"sites",$site,"collect",$colgroup, $collection);
 	    }
 	    else {
-			return &util::filename_cat($ENV{'GSDLHOME'},"collect",$colgroup, $collection);
+			return &FileUtils::filenameConcatenate($ENV{'GSDLHOME'},"collect",$colgroup, $collection);
 	    }
 	}
@@ -1864,10 +1217,11 @@
 {
     my ($output_dir, $convert_basename, $convert_to) = @_;
-    opendir(DIR, $output_dir) || die "can't opendir $output_dir: $!";  
-
     my $page_num = "";
+
+    opendir(DIR, $output_dir) || die "can't opendir $output_dir: $!";
     my @dir_files = grep {-f "$output_dir/$_"} readdir(DIR);
-
-    # Sort files in the directory by page_num    
+    closedir DIR;
+
+    # Sort files in the directory by page_num
     sub page_number {
 	my ($dir) = @_;
@@ -1878,5 +1232,5 @@
     }
 
-    # sort the files in the directory in the order of page_num rather than lexically. 
+    # sort the files in the directory in the order of page_num rather than lexically.
     @dir_files = sort { page_number($a) <=> page_number($b) } @dir_files;
 
@@ -1889,7 +1243,8 @@
     }
 
-    my $item_file = &util::filename_cat($output_dir, $convert_basename.".item");
-    open(FILE,">$item_file");    
-    print FILE "<PagedDocument>\n";
+    my $item_file = &FileUtils::filenameConcatenate($output_dir, $convert_basename.".item");
+    my $item_fh;
+    &FileUtils::openFileHandle($item_file, 'w', \$item_fh);
+    print $item_fh "<PagedDocument>\n";
 
     foreach my $file (@dir_files){
@@ -1897,13 +1252,45 @@
 	    $page_num = page_number($file);
 	    $page_num++ if $starts_at_0; # image numbers start at 0, so add 1
-	    print FILE "   <Page pagenum=\"$page_num\" imgfile=\"$file\" txtfile=\"\"/>\n";
-	} 
-    }
-
-    print FILE "</PagedDocument>\n";
-    close FILE;
-    closedir DIR;
+	    print $item_fh "   <Page pagenum=\"$page_num\" imgfile=\"$file\" txtfile=\"\"/>\n";
+	}
+    }
+
+    print $item_fh "</PagedDocument>\n";
+    &FileUtils::closeFileHandle($item_file, \$item_fh);
     return $item_file;
 }
 
+
+# /** @function augmentINC()
+#  * Prepend a path (if it exists) onto INC but only if it isn't already in
+#  * INC
+#  * @param $new_path The path to add as necessary
+#  * @author jmt12
+#  */
+sub augmentINC
+{
+  my ($new_path) = @_;
+  my $did_add_path = 0;
+  # will need to be replaced with FileUtils::directoryExists() call eventually
+  if (-d $new_path)
+  {
+    my $did_find_path = 0;
+    foreach my $existing_path (@INC)
+    {
+      if ($existing_path eq $new_path)
+      {
+        $did_find_path = 1;
+        last;
+      }
+    }
+    if (!$did_find_path)
+    {
+      unshift(@INC, $new_path);
+      $did_add_path = 1;
+    }
+  }
+  return $did_add_path;
+}
+# /** augmentINC($new_path) **/
+
 1;
