FileDocCategorySizeDatePackage
FileUtils.javaAPI DocGlassfish v2 API54380Fri Jun 15 00:35:14 BST 2007com.sun.enterprise.util.io

FileUtils

public class FileUtils extends Object

Fields Summary
static Logger
_logger
static Logger
_utillogger
private static final int
BUFFER_SIZE
private static final char[]
ILLEGAL_FILENAME_CHARS
private static final String
ILLEGAL_FILENAME_STRING
private static final char
REPLACEMENT_CHAR
private static final char
BLANK
private static final char
DOT
private static String
TMPFILENAME
private static final int
FILE_OPERATION_MAX_RETRIES
private static final int
FILE_OPERATION_SLEEP_DELAY_MS
private static final Level
FILE_OPERATION_LOG_LEVEL
Constructors Summary
private FileUtils()

//Bug 4677074 end
     
    
    
Methods Summary
public static voidappendText(java.lang.String fileName, java.lang.String line)
Appends the given line at the end of given text file. If the given file does not exist, an attempt is made to create it. Note that this method can handle only text files.

param
fileName name of the text file that needs to be appended to
param
line the line to append to
throws
RuntimeException in case of any error - that makes it callable from a code not within try-catch. Note that NPE will be thrown if either argument is null. Note that this method is not tested with String containing characters with 2 bytes.

        RandomAccessFile file = null;
        try
        {
            final String MODE = "rw";
            file = new RandomAccessFile(fileName, MODE);
            file.seek(file.getFilePointer() + file.length());
            file.writeBytes(line);
        }
        catch(Exception e)
        {
            throw new RuntimeException("FileUtils.appendText()", e);
        }
        finally
        {
            try
            {
                if (file != null)
                    file.close();
            }
            catch(Exception e)
            {}
        }
    
public static voidappendText(java.lang.String fileName, java.lang.StringBuffer buffer)

        appendText(fileName, buffer.toString());
    
public static voidcopy(java.lang.String from, java.lang.String to)
Copies a file.

param
from Name of file to copy
param
to Name of new file
exception
IOException if an error while copying the content

        //if(!StringUtils.ok(from) || !StringUtils.ok(to))
        if(from == null || to == null)
            throw new IllegalArgumentException("null or empty filename argument");
        
        File fin  = new File(from);
        File fout = new File(to);
        
        copy(fin, fout);
    
public static voidcopy(java.io.File fin, java.io.File fout)
Copies a file.

param
from File to copy
param
to New file
exception
IOException if an error while copying the content

        if(safeIsDirectory(fin))
        {
            copyTree(fin, fout);
            return;
        }
        
        if(!fin.exists())
            throw new IllegalArgumentException("File source doesn't exist");
        
        //if(fout.exists() && overwrite == false)
        //throw new IOException("File destination exists, overwrite not specified");
        if(!safeIsDirectory(fout.getParentFile()))
            fout.getParentFile().mkdirs();
        
        copy(new FileInputStream(fin), new FileOutputStream(fout));
    
public static voidcopy(java.io.InputStream inStream, java.io.OutputStream outStream)
Copies the bytes from the given input stream to the output stream. It closes the streams afterwards.

param
inStream input stream from the src
param
outStream output stream to the destination
exception
IOException if an error while copying the content

        copyWithoutClose(inStream, outStream);
        
        // closes the streams
        inStream.close();
        outStream.close();
    
public static voidcopyTree(java.io.File din, java.io.File dout)
Copies the entire tree to a new location. Also copies all symlink directories.

param
sourceTree File pointing at root of tree to copy
param
destTree File pointing at root of new tree
exception
IOException if an error while copying the content

        copyTree(din, dout, true);
    
public static voidcopyTree(java.io.File din, java.io.File dout, boolean copySymLinkDirs)
Copies the entire tree to a new location. Symlink directories are only copied when copySymLinksDir is true.

param
sourceTree File pointing at root of tree to copy
param
destTree File pointing at root of new tree
param
copySymLinkDirs if true -- recursively copy symlink directories; otherwise ignore them.
exception
IOException if an error while copying the content

        if(!safeIsDirectory(din))
            throw new IllegalArgumentException("Source isn't a directory");
        
        dout.mkdirs();
        
        if(!safeIsDirectory(dout))
            throw new IllegalArgumentException("Can't create destination directory");
        
        FileListerRelative flr = new FileListerRelative(din);
        flr.setCopySymLinks(copySymLinkDirs);     
        flr.setCopyEmptyDirs(true);
        String[] files = flr.getFiles();
        for(int i = 0; i < files.length; i++)
        {
            File fin  = new File(din, files[i]);
            File fout = new File(dout, files[i]);
            
            if(fin.isDirectory())
                fout.mkdirs();
            else
                copy(fin, fout);
            //System.out.println("Copied " + fin.getPath() + " to " + fout.getPath());
//Bug 4677074			System.out.print(".");
//Bug 4677074 begin
            //_logger.log(Level.FINE,"Copied " + fin.getPath() + " to "+ fout.getPath());
            _logger.log(Level.FINE,".");
//Bug 4677074 end
        }
    
public static voidcopyWithoutClose(java.io.InputStream inStream, java.io.OutputStream outStream)
Copies the bytes from the given input stream to the output stream. It does not close the streams afterwards.

param
inStream input stream from the src
param
outStream output stream to the destination
exception
IOException if an error while copying the content

        BufferedInputStream bis =
            new BufferedInputStream(inStream, BUFFER_SIZE);
        BufferedOutputStream bos =
            new BufferedOutputStream(outStream, BUFFER_SIZE);
        byte[] buf = new byte[BUFFER_SIZE];
        
        int len = 0;
        while (len != -1)
        {
            try
            {
                len = bis.read(buf, 0, buf.length);
            }
            catch (EOFException eof)
            {
                break;
            }
            
            if (len != -1)
            {
                bos.write(buf, 0, len);
            }
        }
        bos.flush();
    
public static java.io.FilecreateTempFile(java.io.File directory)

        File f = null;
        
        try
        {
            f = File.createTempFile(TMPFILENAME, "jar", directory);
        }
        catch (IOException ioe)
        {
//Bug 4677074			ioe.printStackTrace();
//Bug 4677074 begin
            _logger.log(Level.SEVERE,"iplanet_util.io_exception",ioe);
//Bug 4677074 end
        }
        
        f.deleteOnExit(); // just in case
        return f;
    
public static booleandeleteFile(java.io.File f)
Delete a file. If on Windows and the delete fails, run the gc and retry the deletion.

param
file to delete
return
boolean indicating success or failure of the deletion atttempt; returns true if file is absent

            /*
             *The operation succeeds immediately if the file is deleted
             *successfully.  On systems that support symbolic links, the file
             *will be reported as non-existent if the file is a sym link to a
             *non-existent directory.  In that case invoke delete to remove
             *the link before checking for existence, since File.exists on
             *a symlink checks for the existence of the linked-to directory or
             *file rather than of the link itself.
             */
        if (f.delete())
        {
            return true;
        }
        
        boolean log = _utillogger.isLoggable(FILE_OPERATION_LOG_LEVEL);
        String filePath = f.getAbsolutePath();;
        
            /*
             *The deletion failed.  This could be simply because the file
             *does not exist.  In that case, log an appropriate message and
             *return.
             */
        if ( ! f.exists())
        {
            if (log)
            {
                _utillogger.log(Level.FINE, "enterprise_util.delete_failed_absent", filePath);
            }
            return true;
        }
        else
        {
                /*
                 *The delete failed and the file exists.  Log a message if that
                 *level is enabled and return false to indicate the failure.
                 */
            if (log)
            {
                _utillogger.log(FILE_OPERATION_LOG_LEVEL, "enterprise_util.error_deleting_file", filePath);
            }
            return false;
        }
    
public static booleandeleteLeftoverFiles(java.util.Collection leftovers)
Attempts to delete files that could not be deleted earlier and were not overwritten.

On Windows, the method requests garbage collection which may unlock locked files. (The JarFile finalizer closes the file.) On any platform, any remaining leftover files that cannot be cleaned up are marked for delete-on-exit.

Note that the leftovers collection may be modified; a File object is removed if that leftover file is deleted successfully.

param
leftovers a Collection of File objects for undeleted and non-overwritten files
return
whether or not all files were deleted successfully

        if (leftovers.size() == 0)
        {
            return true;
        }
        
        /*
         *If all leftover files are removed then logging at the end of the method
         *(if the logging level is set fine enough) reports all the files that
         *were cleaned up.  To do that create a copy of the original leftover
         *files now because the logic below will remove items from the collection
         *as it successfully removes files.
         */
        Collection<File> originalLeftovers = null;
        boolean log = _utillogger.isLoggable(FILE_OPERATION_LOG_LEVEL);
        if (log)
        {
            originalLeftovers = new ArrayList<File>(leftovers);
        }
        
        /*
         *On Windows, as long as not all leftover files have been cleaned and we have not
         *run the max. number of retries, try again to trigger gc and delete
         *each remaining leftover file.
         */
        int retries = 0;
        if (OS.isWindows())
        {
            retries = doWithRetry(new RetriableWork()
            {
                public boolean workComplete()
                {
                    /*
                     *The removal of the leftover files is done if the collection
                     *is empty.
                     */
                    return leftovers.size() == 0;
                }
                
                public void run()
                {
                    /*
                     *Try to delete all remaining files.  For each successful deletion
                     *remove the corresponding File object from the leftovers collection.
                     */
                    for (Iterator<File> files = leftovers.iterator(); files.hasNext(); )
                    {
                        File f = files.next();
                        if (f.delete())
                        {
                            files.remove();
                        }
                    }
                }
            });
        }
        
        /*
         *Either all leftovers have been removed or at least one remains and we've
         *hit the retry limit...or this is not even a Windows platform.
         */
        if (leftovers.size() == 0 && log)
        {
            _utillogger.log(FILE_OPERATION_LOG_LEVEL, "enterprise_util.leftover_delete_success", new Object [] {
                Integer.valueOf(retries), formatFileCollection(originalLeftovers) } );
        }
        else
        {
            /*
             *Mark all remaining leftovers as delete-on-exit.
             */
            for (File f : leftovers)
            {
                f.deleteOnExit();
            }
            
            /*
             *No retries are performed on non-Windows systems, so log a message
             *that is appropriate to the platform.
             */
            if (OS.isWindows())
            {
                _utillogger.log(Level.WARNING, "enterprise_util.leftover_delete_failure_Windows", new Object [] {
                    Integer.valueOf(retries), formatFileCollection(leftovers)} );
            }
            else
            {
                _utillogger.log(Level.WARNING, "enterprise_util.leftover_delete_failure_nonWindows", new Object [] {
                    formatFileCollection(leftovers)} );
            }
        }
        
        return leftovers.size() == 0;
    
private static intdoWithRetry(com.sun.enterprise.util.io.FileUtils$RetriableWork work)
Executes the supplied work object until the work is done or the max. retry count is reached.

param
work the RetriableWork implementation to be run
return
the number of retries performed; 0 indicates the work succeeded without having to retry

        int retries = 0;
        
        /*
         *Try the work the first time.  Ideally this will work.
         */
        work.run();
        
        /*
         *If the work failed and this is Windows - on which running gc may
         *unlock the locked file - then begin the retries.
         */
        if ( ! work.workComplete() && OS.isWindows())
        {
            _utillogger.log(FILE_OPERATION_LOG_LEVEL, "enterprise_util.perform_gc");
            while ( ! work.workComplete() && retries++ < FILE_OPERATION_MAX_RETRIES)
            {
                try
                {
                    Thread.currentThread().sleep(FILE_OPERATION_SLEEP_DELAY_MS);
                }
                catch (InterruptedException ex)
                {
                }
                System.gc();
                work.run();
            }
        }
        return retries;
    
public static java.lang.StringformatFileCollection(java.util.Collection files)
Creates a String listing the absolute paths of files, separated by the platform's line separator.

param
files the Collection of File objects to be listed
return
String containing the absolute paths of the files with the line separator between them

        StringBuilder sb = new StringBuilder();
        String lineSep = System.getProperty("line.separator");
        String prefix = "";
        for (File f : files)
        {
            sb.append(prefix).append(f.getAbsolutePath());
            prefix = lineSep;
        }
        return sb.toString();
    
public static java.io.FilegetDirectory(java.io.File f)

        String filename = f.getAbsolutePath();
        return new File((new File(filename)).getParent());
    
public static java.lang.StringgetFileContents(java.lang.String fileName)
Method to read a file and return it as String

        
        FileReader fr = null;
        fr = new FileReader(fileName);
        StringWriter sr = new StringWriter();
        
        try
        {
            char[] buf = new char[1024];
            int len = 0;
            while (len != -1)
            {
                try
                {
                    len = fr.read(buf, 0, buf.length);
                }
                catch (EOFException eof)
                {
                    break;
                }
                if (len != -1)
                {
                    sr.write(buf, 0, len);
                }
            }
            
            fr.close();
            sr.close();
            
            return sr.toString();
            
        }
        finally
        {
            if (fr != null)
            {
                try
                {
                    fr.close();
                }
                catch (IOException ioe)
                {
                }
            }
        }
    
public static java.lang.StringgetIllegalFilenameCharacters()

        return ILLEGAL_FILENAME_STRING;
    
public static booleanhasExtension(java.lang.String filename, java.lang.String ext)

        if(filename == null || filename.length() <= 0)
            return false;
        
        return filename.endsWith(ext);
    
public static booleanhasExtension(java.io.File f, java.lang.String ext)

        if(f == null || !f.exists())
            return false;
        
        return f.getName().endsWith(ext);
    
public static booleanhasExtensionIgnoreCase(java.lang.String filename, java.lang.String ext)

        if(filename == null || filename.length() <= 0)
            return false;
        
        return filename.toLowerCase().endsWith(ext.toLowerCase());
    
public static booleanhasExtensionIgnoreCase(java.io.File f, java.lang.String ext)

        if(f == null || !f.exists())
            return false;
        
        return f.getName().toLowerCase().endsWith(ext.toLowerCase());
    
public static booleanisArchive(java.lang.String filename)

        return isWar(filename) || isRar(filename) || isJar(filename) || isZip(filename) || isEar(filename);
    
public static booleanisArchive(java.io.File f)

        return isWar(f) || isRar(f) || isJar(f) || isZip(f) || isEar(f);
    
public static booleanisEar(java.lang.String filename)

        return hasExtension(filename, ".ear");
    
public static booleanisEar(java.io.File f)

        return hasExtension(f, ".ear");
    
public static booleanisFriendlyFilename(java.lang.String filename)

        if(!isValidString(filename))
            return false;
        
        if(filename.indexOf(BLANK) >= 0 || filename.indexOf(DOT) >= 0)
            return false;
        
        return isLegalFilename(filename);
    
public static booleanisJar(java.lang.String filename)

        return hasExtension(filename, ".jar");
    
public static booleanisJar(java.io.File f)

        return hasExtension(f, ".jar");
    
public static booleanisLegalFilename(java.lang.String filename)

        if(!isValidString(filename))
            return false;
        
        for(int i = 0; i < ILLEGAL_FILENAME_CHARS.length; i++)
            if(filename.indexOf(ILLEGAL_FILENAME_CHARS[i]) >= 0)
                return false;
        
        return true;
    
public static booleanisRar(java.lang.String filename)

        return hasExtension(filename, ".rar");
    
public static booleanisRar(java.io.File f)

        return hasExtension(f, ".rar");
    
static booleanisValidString(java.lang.String s)

        return ((s != null) && (s.length() != 0));
    
public static booleanisWar(java.lang.String filename)

        return hasExtension(filename, ".war");
    
public static booleanisWar(java.io.File f)

        return hasExtension(f, ".war");
    
public static booleanisZip(java.lang.String filename)

        return hasExtensionIgnoreCase(filename, ".zip");
    
public static booleanisZip(java.io.File f)

        return hasExtensionIgnoreCase(f, ".zip");
    
public static voidliquidate(java.io.File parent)

        whack(parent);
    
public static java.io.File[]listAllFiles(java.io.File dirName, java.lang.String ext)
Returns an array of abstract pathnames that matches with the given file extension. If the given abstract pathname does not denote a directory, then this method returns null. If there is no matching file under the given directory and its sub directories, it returns null;

param
dirName dir name under which search will begin
param
ext file extension to look for
return
an array of abstract pathnames that matches with the extension

        File[] target  = null;
        List list      = searchDir(dirName, ext);
        
        if ( (list != null) && (list.size() > 0) )
        {
            target = new File[list.size()];
            target = (File[]) list.toArray(target);
        }
        
        return target;
    
public static voidmain(java.lang.String[] args)

        try
        {
            System.out.println(smartRename(new File("C:/temp/test")));
        }
        catch(Throwable t)
        {
            t.printStackTrace();
        }
                /*
                try
                {
                        String ret = recursiveChmod(new File("c:/temp"), "rwxr-----");
                        System.out.println("recursiveChmod returned: " + ret);
                }
                catch(Throwable t)
                {
                        t.printStackTrace();
                }
                //_logger.log(Level.SEVERE,"iplanet_util.io_exception", new IOException());
                //System.out.println("xxxxxxxxxx");
                 **/
        appendText("empty.txt", "text line");
    
public static java.lang.StringmakeForwardSlashes(java.lang.String inputStr)
Returns a String with uniform slashes such that all the occurances of '\\' are replaced with '/'. In other words, the returned string will have all forward slashes. Accepts non-null strings only.

param
a non null String
return
a String which does not contain `\\` character

        if(inputStr == null)
            throw new IllegalArgumentException("null String FileUtils.makeForwardSlashes");
        return ( inputStr.replace('\\", '/") );
    
public static java.lang.StringmakeFriendlyFileName(java.lang.String filename)

        // OK -- I hate having to go back in here to see if the 'N'
        // is uppercase or lowercase.  Let's have both!!
        return makeFriendlyFilename(filename);
    
public static java.lang.StringmakeFriendlyFileNameNoExtension(java.lang.String filename)

        // OK -- I hate having to go back in here to see if the 'N'
        // is uppercase or lowercase.  Let's have both!!
        return makeFriendlyFilenameNoExtension(filename);
    
public static java.lang.StringmakeFriendlyFilename(java.lang.String filename)

        if(isFriendlyFilename(filename))
            return filename;
        
        String ret = makeLegalNoBlankFileName(filename);
        // only replace the "." in the archive type suffix
        if (ret.endsWith(".ear"))
        {
            ret = ret.substring(0, ret.indexOf(".ear"));
            ret = ret + "_ear";
        }
        else if (ret.endsWith(".war"))
        {
            ret = ret.substring(0, ret.indexOf(".war"));
            ret = ret + "_war";
        }
        else if (ret.endsWith(".jar"))
        {
            ret = ret.substring(0, ret.indexOf(".jar"));
            ret = ret + "_jar";
        }
        else if (ret.endsWith(".rar"))
        {
            ret = ret.substring(0, ret.indexOf(".rar"));
            ret = ret + "_rar";
        }
        
        return ret;
    
public static java.lang.StringmakeFriendlyFilenameNoExtension(java.lang.String filename)

        int index = filename.lastIndexOf('.");
        
        if(index > 0)
            filename = filename.substring(0, index);
        
        return(makeFriendlyFilename(filename));
    
public static java.lang.StringmakeLegalFilename(java.lang.String filename)

        if(isLegalFilename(filename))
            return filename;
        
        for(int i = 0; i < ILLEGAL_FILENAME_CHARS.length; i++)
            filename = filename.replace(ILLEGAL_FILENAME_CHARS[i], REPLACEMENT_CHAR);
        
        return filename;
    
public static java.lang.StringmakeLegalNoBlankFileName(java.lang.String filename)

        return  makeLegalFilename(filename).replace(
            BLANK, REPLACEMENT_CHAR);
    
public static java.io.FileOutputStreamopenFileOutputStream(java.io.File out)
Opens a stream to the specified output file, retrying if necessary.

param
out the output File for which a stream is needed
return
the FileOutputStream
exception
IOException for any errors opening the stream

        FileOutputStreamWork work = new FileOutputStreamWork(out);
        int retries = doWithRetry(work);
        if (work.workComplete())
        {
            return work.getStream();
        }
        else
        {
            IOException ioe = new IOException();
            ioe.initCause(work.getLastError());
            throw ioe;
        }
    
public static java.lang.StringreadSmallFile(java.lang.String fileName)
A utility routine to read a text file efficiently and return the contents as a String. Sometimes while reading log files of spawned processes this kind of facility is handy. Instead of opening files, coding FileReaders etc. this method could be employed. It is expected that the file to be read is small .

param
fileName String representing absolute path of the file
return
String representing the contents of the file, empty String for an empty file
throws
java.io.IOException if there is an i/o error.
throws
java.io.FileNotFoundException if the file could not be found

        return (readSmallFile(new File(fileName)) );
    
public static java.lang.StringreadSmallFile(java.io.File file)

        final BufferedReader bf = new BufferedReader(new FileReader(file));
        final StringBuilder sb = new StringBuilder(); //preferred over StringBuffer, no need to synchronize
        String line = null;
        try
        {
            while ( (line = bf.readLine()) != null )
            {
                sb.append(line);
                sb.append(System.getProperty("line.separator"));
            }
        }
        finally
        {
            try
            {
                bf.close();
            }
            catch (Exception e)
            {}
        }
        return ( sb.toString() );
    
public static java.lang.StringrecursiveChmod(java.io.File dirOrFile, java.lang.String permissions)
Recursively changes the file permissions via native code.

param
dirOrFile the directory or file to chmod (recursively if directory)
param
permissions a String representing permissions.

permissions must be exactly like so: "rwxrwxrwx" which is user-group-others put a dash (or anything else) in a position that you don't want the permission set. e.g. rwx -> user, r -> group, nothing -> others "rwxr-----"

throws
NativeIOException -- if there was an error
return
String suitable for logging about the success

        if(dirOrFile == null || !dirOrFile.exists())
            throw new NativeIOException("File doesn't exist: " + dirOrFile);
        
        if(permissions == null)
            throw new NativeIOException("null permissions string.");
        
        permissions = permissions.toLowerCase(); // using R,W,X should not be an error!
        verifyPermissions(permissions);
        
        int ret = recursiveChmodNative(dirOrFile.getAbsolutePath(), permissions);
        
        NativeResults nr		= new NativeResults(ret);
        NativeIOException ne	= nr.getResultException();
        
        if(ne == null)
            return nr.getResultString();
        else
            throw ne;
    
public static native intrecursiveChmodNative(java.lang.String dirOrFile, java.lang.String permissions)

public static java.lang.StringrecursiveChown(java.io.File dirOrFile)
This version will set the owner to the current user

param
dirOrFile - File or Directory to change owner
throws
NativeIOException if there was an error
return
a success String suitable for logging.

        return recursiveChown(dirOrFile, null);
    
public static java.lang.StringrecursiveChown(java.io.File dirOrFile, java.lang.String user)
This version will set the owner to the specified user

param
dirOrFile - File or Directory to change owner
throws
NativeIOException if there was an error
return
a success String suitable for logging.

        if(dirOrFile == null || !dirOrFile.exists())
            throw new NativeIOException("File doesn't exist: " + dirOrFile);
        
        String fname = dirOrFile.getAbsolutePath();
        int ret = 0;
        
        if(!isValidString(user))
            ret = recursiveChownNative(fname);
        else
            ret = recursiveChownNative(fname, user);
        
        NativeResults nr		= new NativeResults(ret);
        NativeIOException ne	= nr.getResultException();
        
        if(ne == null)
            return nr.getResultString();
        else
            throw ne;
    
public static native intrecursiveChownNative(java.lang.String dirOrFile, java.lang.String user)

public static native intrecursiveChownNative(java.lang.String dirOrFile)

public static booleanrenameFile(java.io.File fromFile, java.io.File toFile)
Rename, running gc on Windows if needed to try to force open streams to close.

param
file to be renamed
param
new name for the renamed file
return
boolean result of the rename attempt

        boolean log = _utillogger.isLoggable(FILE_OPERATION_LOG_LEVEL) || _utillogger.isLoggable(Level.FINE);
        
        RenameFileWork renameWork = new RenameFileWork(fromFile, toFile);
        int retries = doWithRetry(renameWork);
        boolean result = renameWork.workComplete();
        
        String fromFilePath = null;
        String toFilePath = null;
        if (log || ! result)
        {
            fromFilePath = fromFile.getAbsolutePath();
            toFilePath = toFile.getAbsolutePath();
        }
        
            /*
             *If the rename worked, then write an appropriate log message if the
             *logging level allows.
             */
        if (result)
        {
            if (log)
            {
                    /*
                     *If the rename worked without retries, then log a FINE message.
                     *If retries were needed then use the configured
                     *FILE_OPERATION_LOG_LEVEL.
                     */
                if (retries == 0)
                {
                    if (_utillogger.isLoggable(Level.FINE))
                    {
                        _utillogger.log(Level.FINE, "enterprise_util.rename_initial_success", new Object [] {
                            fromFilePath, toFilePath } );
                    }
                }
                else
                {
                    _utillogger.log(FILE_OPERATION_LOG_LEVEL, "enterprise_util.retry_rename_success", new Object []
                    { fromFilePath, toFilePath, Integer.valueOf(retries) } );
                }
            }
        }
        else
        {
                /*
                 *The rename has failed.  Write a warning message.
                 */
            _utillogger.log(Level.WARNING, "enterprise_util.retry_rename_failure", new Object []
            { fromFilePath, toFilePath, Integer.valueOf(retries) } );
        }
        return result;
    
public static java.lang.StringrevertFriendlyFilename(java.lang.String filename)

        
        //first, revert the file extension
        String name = revertFriendlyFilenameExtension(filename);
        
        //then, revert the rest of the string
        return name.replace(REPLACEMENT_CHAR, '/");
    
public static java.lang.StringrevertFriendlyFilenameExtension(java.lang.String filename)

        if (filename == null ||
            !(filename.endsWith("_ear") || filename.endsWith("_war") ||
            filename.endsWith("_jar") || filename.endsWith("_rar")) )
        {
            return filename;
        }
        
        String extension = "";
        if (filename.endsWith("_ear"))
        {
            filename = filename.substring(0, filename.indexOf("_ear"));
            extension = ".ear";
        }
        else if (filename.endsWith("_war"))
        {
            filename = filename.substring(0, filename.indexOf("_war"));
            extension = ".war";
        }
        else if (filename.endsWith("_jar"))
        {
            filename = filename.substring(0, filename.indexOf("_jar"));
            extension = ".jar";
        }
        else if (filename.endsWith("_rar"))
        {
            filename = filename.substring(0, filename.indexOf("_rar"));
            extension = ".rar";
        }
        return filename + extension;
    
public static java.io.FilesafeGetCanonicalFile(java.io.File f)

        
        if(f == null)
            return null;
        
        try
        {
            return f.getCanonicalFile();
        }
        catch(IOException e)
        {
            return f.getAbsoluteFile();
        }
    
public static java.lang.StringsafeGetCanonicalPath(java.io.File f)

        if(f == null)
            return null;
        
        try
        {
            return f.getCanonicalPath();
        }
        catch(IOException e)
        {
            return f.getAbsolutePath();
        }
    
public static booleansafeIsDirectory(java.io.File f)

        if(f == null || !f.exists() || !f.isDirectory())
            return false;
        
        return true;
    
public static booleansafeIsDirectory(java.lang.String s)

        return safeIsDirectory(new File(s));
    
public static booleansafeIsRealDirectory(java.lang.String s)

        return safeIsRealDirectory(new File(s));
    
public static booleansafeIsRealDirectory(java.io.File f)

        if(safeIsDirectory(f) == false)
            return false;
        
        
        
        // these 2 values while be different for symbolic links
        String canonical	= safeGetCanonicalPath(f);
        String absolute		= f.getAbsolutePath();
        
        if(canonical.equals(absolute))
            return true;
        
                /* Bug 4715043 -- WHOA -- Bug Obscura!!
                 * In Windows, if you create the File object with, say, "d:/foo", then the
                 * absolute path will be "d:\foo" and the canonical path will be "D:\foo"
                 * and they won't match!!!
                 **/
        if(OS.isWindows() && canonical.equalsIgnoreCase(absolute))
            return true;
        
        return false;
    
public static java.util.ListsearchDir(java.io.File dirName, java.lang.String ext)
Returns a list of abstract pathnames that matches with the given file extension. If the given abstract pathname does not denote a directory, then this method returns null. If there is no matching file under the given directory and its sub directories, it returns an empty list.

param
dirName dir name under which search will begin
param
ext file extension to look for
return
a list of abstract pathnames of type java.io.File that matches with the given extension

        List targetList = null;
        
        if (dirName.isDirectory())
        {
            targetList = new ArrayList();
            
            File[] list = dirName.listFiles();
            
            for (int i=0; i<list.length; i++)
            {
                if (list[i].isDirectory())
                {
                    targetList.addAll( searchDir(list[i], ext) );
                }
                else
                {
                    String name = list[i].toString();
                    if ( hasExtension(name, ext) )
                    {
                        targetList.add(list[i]);
                    }
                }
            }
        }
        
        return targetList;
    
public static java.io.FilesmartRename(java.io.File original)
Windows has BIG issues renaming a directory that is open somnewhere -- e.g. if a DOS box is opened anywhere in that directory. This method will try to do a "virtual renaming" if there are problems I.e. it attempts to do a simple rename, if that fails it will copy everything under the original directory to the renamed directory. Then it will delete everything under the original directory that the OS will allow it to. NOTE: if the proposed new name already exists - I will try to whack it. bnevins April 2003

returns
the renamed directory-name

        if(original == null)
            throw new IllegalArgumentException("null argument");
        
        String originalName = original.getAbsolutePath();
        
        if(!safeIsDirectory(original))
            throw new IOException("Directory doesn't exist: " + originalName);
        
        // let's try to work with "_old" added to name...
        
        String renamedName	= originalName + "_old";
        File renamed		= new File(renamedName);
        
        if(renamed.exists())
        {
            whack(renamed);
            
            // it might have failed:
            if(renamed.exists())
            {
                for(int i = 0; i < 1000; i++)
                {
                    String name = renamedName + i;
                    renamed = new File(name);
                    
                    try
                    { whack(renamed); }
                    catch(Throwable t)
                    { /* ignore!! */ }
                    
                    if(!renamed.exists())
                    {
                        // found one!!!
                        renamedName = name;
                        break;
                    }
                }
                // once more in case we went through all 1000!
                if(renamed.exists())
                    throw new IOException("Tried 1000 possible rename directory names.  None worked!");
            }
        }
        
        // whew!
        
        // try a simple rename...
        
        if(original.renameTo(renamed))
            return renamed;
        
        // OK -- we'return probably in Windows and something is referencing original.
        
        copyTree(original, renamed);
        whack(original);	// this will delete whatever is possible to delete...
        
        return renamed;
    
public static voidvalidateWindowsFilePathLength(java.lang.String fullPath)
Make sure the specified path is a legal length on Windows.

param
fullPath the String holding the path to check
throws
IOException if the path is too long

        /*
         *No longer needed because 1.5.0-06 now avoids the Windows file path
         *length limitation.
         */
        return;
    
public static voidvalidateWindowsFilePathLength(java.io.File file)
Make sure the specified path is a legal length on Windows.

param
file the File to check
throws
IOException if the path is too long

        validateWindowsFilePathLength(file.getAbsolutePath());
    
private static voidverifyPermissions(java.lang.String per)

        // brace yourself for some involved argument checking.
        // It's not pretty but it *is* neccessary.
        
        if(per == null)
            throw new NativeIOException("null permissions string.");
        if(per.length() != 9)
            throw new NativeIOException("permissions string must be exactly" +
                " 9 characters long.  It is " + per.length() + " characters long.");
        
        // make sure every character is r, w, x, or -
        String err1 = "permissions string has a bad character ('";
        String err2 = "') at position #";
        String err3 = ".  Expected '-' or '";
        String err4 = "'";
        
        for(int i = 0; i < 9; i++)
        {
            
            char c = per.charAt(i);
            int pos = i % 3;	// 0->r, 1->w, 2->x
            
            if(pos == 0)
            {
                if(c != 'r" && c != '-")
                    throw new NativeIOException(err1 + c + err2 + (i + 1) + err3 + 'r" + err4);
            }
            else if(pos == 1)
            {
                if(c != 'w" && c != '-")
                    throw new NativeIOException(err1 + c + err2 + (i + 1) + err3 + 'w" + err4);
            }
            else if(pos == 2)
            {
                if(c != 'x" && c != '-")
                    throw new NativeIOException(err1 + c + err2 + (i + 1) + err3 + 'x" + err4);
            }
        }
    
public static booleanwhack(java.io.File parent)
Deletes a directory and its contents.

If this method encounters a symbolic link in the subtree below "parent" then it deletes the link but not any of the files pointed to by the link. Note that whack will delete files if a symbolic link appears in the path above the specified parent directory in the path.

param
parent the File at the top of the subtree to delete
return
success or failure of deleting the directory

        return whack(parent, null);
    
public static booleanwhack(java.io.File parent, java.util.Collection undeletedFiles)
Deletes a directory and its contents.

If this method encounters a symbolic link in the subtree below "parent" then it deletes the link but not any of the files pointed to by the link. Note that whack will delete files if a symbolic link appears in the path above the specified parent directory in the path.

param
parent the File at the top of the subtree to delete
return
success or failure of deleting the directory

        try
        {
                /*
                 *Resolve any links up-stream from this parent directory and
                 *then whack the resulting resolved directory.
                 */
            return whackResolvedDirectory(parent.getCanonicalFile(), undeletedFiles);
        }
        catch (IOException ioe)
        {
            _utillogger.log(Level.SEVERE, "iplanet_util.io_exception", ioe);
            return false;
        }
    
private static booleanwhackResolvedDirectory(java.io.File parent, java.util.Collection undeletedFiles)
Deletes a directory and its contents.

The whackResolvedDirectory method is invoked with a File argument in which any upstream file system links have already been resolved. This method will treate Any file passed in that does not have the same absolute and canonical path - as evaluated in safeIsRealDirectory - as a link and will delete the link without deleting any files in the linked directory.

param
parent the File at the top of the subtree to delete
return
success or failure of deleting the directory

                /*
                 *Do not recursively delete the contents if the current parent
                 *is a symbolic link.
                 */
        if (safeIsRealDirectory(parent))
        {
            File[] kids = parent.listFiles();
            
            for(int i = 0; i < kids.length; i++)
            {
                File f = kids[i];
                
                if(f.isDirectory())
                    whackResolvedDirectory(f, undeletedFiles);
                else
                    if ( ! deleteFile(f) && undeletedFiles != null)
                    {
                    undeletedFiles.add(f);
                    }
                
            }
        }
        
                /*
                 *Delete the directory or symbolic link.
                 */
        return deleteFile(parent);