/*==========================================================================*\
| $Id: FileUtilities.java,v 1.9 2011/05/27 15:30:56 stedwar2 Exp $
|*-------------------------------------------------------------------------*|
| Copyright (C) 2006-2008 Virginia Tech
|
| This file is part of Web-CAT.
|
| Web-CAT is free software; you can redistribute it and/or modify
| it under the terms of the GNU Affero General Public License as published
| by the Free Software Foundation; either version 3 of the License, or
| (at your option) any later version.
|
| Web-CAT 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 Affero General Public License
| along with Web-CAT; if not, see <http://www.gnu.org/licenses/>.
\*==========================================================================*/
package net.sf.webcat;
import java.io.*;
import java.util.*;
import java.util.zip.*;
// -------------------------------------------------------------------------
/**
* Provides utility methods for manipulating files and directories.
*
* @author stedwar2
* @author Last changed by $Author: stedwar2 $
* @version $Revision: 1.9 $, $Date: 2011/05/27 15:30:56 $
*/
public class FileUtilities
{
//~ Constructors ..........................................................
// ----------------------------------------------------------
/**
* This constructor is private since this class should not be
* instantiated. It simply provides a few static helper methods
* used by other classes.
*/
private FileUtilities()
{
// No actions to perform, since this class has no state.
}
//~ Methods ...............................................................
// ----------------------------------------------------------
/**
* Unzips the zipfile in the output directory. This method is
* provided purely for use by the Bootstrap code. All other code
* should use the org.webcat.archives.ArchiveManager
* class instead.
*
* @param zipFile the zip file
* @param outputDir full path of the output directory
* @throws java.io.IOException if occurs during unzipping
*/
public static void unZip(ZipFile zipFile, File outputDir)
throws java.io.IOException
{
Enumeration<? extends ZipEntry> e = zipFile.entries();
while (e.hasMoreElements())
{
ZipEntry entry = e.nextElement();
File entryFile = new File(outputDir, entry.getName());
if (entry.isDirectory())
{
entryFile.mkdirs();
}
else
{
File parent = entryFile.getParentFile();
if (!parent.exists())
{
parent.mkdirs();
}
BufferedInputStream in = new BufferedInputStream(
zipFile.getInputStream(entry));
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(entryFile));
copyStream(in, out);
in.close();
out.close();
long modTime = entry.getTime();
if (modTime != -1)
{
entryFile.setLastModified(modTime);
}
}
}
}
// ----------------------------------------------------------
/**
* Copies the contents of an input stream onto an existing output
* stream. The output stream is flushed when the operation
* is complete.
*
* @param in the input stream to copy
* @param out the destination
* @throws IOException if there are IO errors
*/
public static void copyStream(InputStream in, OutputStream out)
throws IOException
{
// read in increments of BUFFER_SIZE
byte[] b = new byte[BUFFER_SIZE];
int count = in.read(b);
while (count > -1)
{
out.write(b, 0, count);
count = in.read(b);
}
out.flush();
}
// ----------------------------------------------------------
/**
* Checks to see if the given directory contains a file with the given
* name.
* @param dir The directory to check.
*
* @param filename the name of the file
* @return True if there is a file in the directory with the given
* file name.
*/
public static boolean inDirectory(File dir, String filename)
{
if (dir != null && filename != null && dir.isDirectory())
{
for (File file : dir.listFiles())
{
if (filename.equals(file.getName()))
{
return true;
}
}
}
return false;
}
// ----------------------------------------------------------
/**
* Deletes older versions of the update files found in the specified
* directory.
* @param Directory containing update files
*/
public static void deleteOlderFiles(File dir)
{
if (dir != null && dir.isDirectory())
{
File[] dirFiles = dir.listFiles();
for (int i = 0; i+1 < dirFiles.length; i++)
{
if (dirFiles[i] == null)
{
continue;
}
String[] iFile = dirFiles[i].getName().split("\\_");
for (int j = i+1; j < dirFiles.length; j++)
{
String[] jFile = dirFiles[j].getName().split("\\_");
if (iFile[0].equals(jFile[0]))
{
iFile = iFile[1].split("\\.");
jFile = jFile[1].split("\\.");
int delete;
if (iFile[2].compareTo(jFile[2]) > 0)
{
delete = j;
}
else
{
delete = i;
}
if (iFile[1].compareTo(jFile[1]) > 0)
{
delete = j;
}
else
{
delete = i;
}
if (iFile[0].compareTo(jFile[0]) > 0)
{
delete = j;
}
else
{
delete = i;
}
dirFiles[delete].delete();
dirFiles[delete] = null;
}
}
}
}
}
// ----------------------------------------------------------
/**
* Return a canonical version of the file name, using "/" as the path
* seperator instead of "\".
*
* @param name the File with the name to convert
* @return the canonical version of the file's name
*/
public static String normalizeFileName(File name)
{
try
{
return name.getCanonicalPath().replace('\\', '/');
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
// ----------------------------------------------------------
/**
* Return a canonical version of the file name, using "/" as the path
* seperator instead of "\".
*
* @param name the name to convert
* @return the canonical version of the file's name
*/
public static String normalizeFileName(String name)
{
return normalizeFileName(new File(name));
}
// ----------------------------------------------------------
/**
* Recursively deletes a directory
*
* @param dir the File object for the directory
* @param preserve a Map with String keys indicating elements within
* the target directory to keep (that is, not to delete); this
* parameter can be null if none are to be preserved.
* @return true if the directory was removed, false if it was not
* (because at least some of its contents were preserved).
*/
public static boolean deleteDirectory(File dir, Map<String, ?> preserve)
{
if (dir == null || !dir.exists())
{
return true;
}
File[] files = dir.listFiles();
boolean deletedAll = true;
for (int i = 0; i < files.length; i++)
{
if (preserve != null)
{
// This is just a linear search, because the preserve
// lists are so short in general that it is not worth the
// effort to speed them up.
if (preserve.containsKey(normalizeFileName(files[i])))
{
deletedAll = false;
continue;
}
}
if (files[i].isDirectory())
{
deletedAll = deleteDirectory(files[i], preserve)
&& deletedAll;
}
files[i].delete();
}
if (deletedAll)
{
dir.delete();
}
return deletedAll;
}
// ----------------------------------------------------------
/**
* Gets the CRC checksum of a file.
* @param file The file to compute the checksum of.
* @return the checksum value
*/
public static long getCRCChecksum(File file)
{
try
{
CheckedInputStream cis =
new CheckedInputStream(new FileInputStream(file), new CRC32());
byte[] buf = new byte[BUFFER_SIZE];
while (cis.read(buf) >= 0)
{
// nothing to do ... just accumulating checksum
}
long checksum = cis.getChecksum().getValue();
cis.close();
return checksum;
}
catch (FileNotFoundException e)
{
// silently swallow exception
}
catch (IOException e)
{
// silently swallow exception
}
return 0;
}
//~ Instance/static variables .............................................
static final private int BUFFER_SIZE = 65536;
}