/*
Copyright (c) 2003 eInnovation Inc. All rights reserved
This library is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any later version.
This library 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 Lesser General Public License for more details.
*/
package com.openedit.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Some file utility methods such as recursive delete.
*/
public class FileUtils
{
protected Set fieldInvalidChars;
OutputFiller fieldFiller = new OutputFiller();
private static final Log log = LogFactory.getLog(FileUtils.class);
/**
* Create a temporary directory with a unique name beginning with the given
* prefix.
*
* @param inPrefix
* The prefix for the created directory
*
* @return DOCME
*
* @throws IOException
* DOCME
*/
public File createTempDir( String inPrefix ) throws IOException
{
File tempDir = File.createTempFile( inPrefix, null );
tempDir.delete();
tempDir.mkdir();
return tempDir;
}
/**
* DOCME
*
* @param fname
* DOCME
*/
public void deleteAll( String fname )
{
File f = new File( fname );
deleteAll( f );
}
/**
* Deletes any files in this directory that match the wildcard
* @param inMatch
*/
public void deleteMatch( String inMatch )
{
//get the parent, list the children, find the match, delete
File search = new File( inMatch );
File dir = search.getParentFile();
File[] all = dir.listFiles();
if ( all != null)
{
for (int i = 0; i < all.length; i++)
{
File f = all[i];
if ( PathUtilities.match(f.getName(), search.getName() ) )
{
log.info("deleted " + f.getName());
f.delete(); //should this do dirs?
}
}
}
}
public boolean deleteOlderVersions( String inDir )
{
System.gc();
boolean requiresRestart = false;
Map map = new HashMap();
//get the parent, list the children, find the match, delete
File dir = new File( inDir );
File[] all = dir.listFiles();
if ( all != null)
{
for (int i = 0; i < all.length; i++)
{
File f = all[i];
String fileName = f.getName();
int dashIndex = fileName.lastIndexOf('-');
if (dashIndex >= 0)
{
String base = fileName.substring(0, dashIndex);
String version = fileName.substring(dashIndex + 1 );
String highestVersion = (String)map.get(base);
if (highestVersion == null || highestVersion.compareTo(version) < 0)
{
map.put(base, version);
}
}
}
for (int i = 0; i < all.length; i++)
{
File f = all[i];
String fileName = f.getName();
int dashIndex = fileName.lastIndexOf('-');
if (dashIndex >= 0)
{
String base = fileName.substring(0, dashIndex);
String version = fileName.substring(dashIndex + 1);
String highestVersion = (String)map.get(base);
if (!version.equals(highestVersion))
{
if (f.delete())
{
log.info("deleting " + f.getName());
}
else
{
log.info("deleting " + f.getName() + " on exit");
f.deleteOnExit();
requiresRestart = true;
}
}
}
}
}
return requiresRestart;
}
public void deleteAll( File file )
{
if (file.isDirectory())
{
// If it's a dir, then delete everything in it.
File[] fileList = file.listFiles();
if (fileList != null)
{
for ( int idx = 0; idx < fileList.length; idx++ )
deleteAll( fileList[idx] );
}
}
// Now delete ourselves, whether a file or a dir.
file.delete();
}
public void copyFileByMatch( String inMatch, String outDir) throws IOException
{
File out = new File( outDir );
out.mkdirs();
copyFileByMatch(inMatch, out );
}
public void copyFileByMatch( String inMatch, File outDir) throws IOException
{
File file = new File( inMatch );
File dir = file.getParentFile();
File[] all = dir.listFiles();
if ( all != null)
{
for (int i = 0; i < all.length; i++)
{
File f = all[i];
if ( PathUtilities.match(f.getName(), file.getName() ) )
{
copyFiles(f, outDir);
}
}
}
}
/**
* DOCME
*
* @param inSource
* DOCME
* @param inDest
* DOCME
* @param inBuffer
* DOCME
*
* @throws IOException
* DOCME
*/
public void dirCopy( File inSource, File inDest ) throws IOException
{
if (inSource.isDirectory())
{
inDest.mkdirs();
File[] files = inSource.listFiles();
if( files != null)
{
for ( int i = 0; i < files.length; i++ )
{
// The child directory
File newDest = new File( inDest, files[i].getName() );
if (files[i].isDirectory())
{
dirCopy( files[i], newDest );
}
else
{
fileCopy( files[i], newDest );
}
}
}
}
}
/**
* Does a move even if the directory already exist
* Also creates a directory for file to be moved into
* @param inSource
* @param inDest
* @throws IOException
*/
public void move( String inSource, String inDest ) throws IOException
{
move( new File( inSource), new File( inDest));
}
public void move( File inSource, File inDest ) throws IOException
{
move(inSource, inDest, false);
}
public void move(File inSource, File inDest, boolean inForce) throws IOException
{
if (inSource.isDirectory())
{
inDest.mkdirs();
File[] files = inSource.listFiles();
if( files != null)
{
for ( int i = 0; i < files.length; i++ )
{
// The child directory
File newDest = new File( inDest, files[i].getName() );
if (files[i].isDirectory())
{
move( files[i], newDest, inForce );
}
else
{
renameFile(files[i], newDest, inForce );
}
}
}
inSource.delete();
}
else
{
if( inDest.isDirectory())
{
inDest = new File( inDest, inSource.getName());
}
else
{
inDest.getParentFile().mkdirs();
}
renameFile(inSource, inDest, inForce);
}
}
protected void renameFile(File inSource, File inDest, boolean inForce) throws IOException
{
if( !inSource.renameTo( inDest ) )
{
if(inForce)
{
copyFiles(inSource,inDest);
boolean deleted = inSource.delete();
if(!deleted){
log.info("could not delete file - " + inSource);
}
return;
}
throw new IOException("Could not move " + inSource.getPath() + " to " + inDest.getPath() + " file may already exist. Use forced=true");
}
}
/**
* DOCME
*
* @param src
* DOCME
* @param dst
* DOCME
* @param buffer
* DOCME
*
* @throws IOException
* DOCME
*/
public void fileCopy( File src, File dst ) throws IOException
{
fieldFiller.fill(src,dst);
// Preserve the modification date of the original file.
dst.setLastModified( src.lastModified() );
}
public void copyFiles( String source, String destination ) throws IOException
{
copyFiles( new File( source ), new File( destination ) );
}
public void copyFiles( File source, File destination ) throws IOException
{
if (source.isDirectory())
{
if( destination.exists() && !destination.isDirectory() )
{
destination.delete();
}
destination.mkdirs();
//loop over all the sub files
File[] children = source.listFiles();
for ( int i = 0; i < children.length; i++ )
{
copyFiles( children[i], new File( destination, children[i].getName() ) );
}
}
else
{
if( destination.isDirectory() )
{
copyFiles( source,new File( destination , source.getName() ) );
}
else
{
destination.getParentFile().mkdirs();
fieldFiller.fill( source,destination );
destination.setLastModified(source.lastModified());
}
}
}
/**
* This closes the input stream
* @param inInput
* @param inOutputFile
* @throws IOException
*/
public void writeFile( InputStream inInput, File inOutputFile ) throws IOException
{
//TODO: Could probably start using java.nio classes
// Write the content
// Create any parent directories, if necessary.
inOutputFile.getParentFile().mkdirs();
OutputStream out = new FileOutputStream( inOutputFile );
try
{
fieldFiller.fill( inInput, out );
out.flush();
}
finally
{
if ( inInput != null)
{
inInput.close();
}
out.close();
}
}
/**
* @param inIn
*/
public static void safeClose(Reader inIn)
{
if ( inIn != null)
{
try
{
inIn.close();
}
catch (IOException ex)
{
log.error(ex);
}
}
}
public static void safeClose(InputStream inIn)
{
if ( inIn != null)
{
try
{
inIn.close();
}
catch (IOException ex)
{
log.error(ex);
}
}
}
public static void safeClose(OutputStream inIn)
{
if ( inIn != null)
{
try
{
inIn.close();
}
catch (IOException ex)
{
log.error(ex);
}
}
}
public static void safeClose(Writer inIn)
{
if ( inIn != null)
{
try
{
inIn.close();
}
catch (IOException ex)
{
log.error(ex);
}
}
}
public void replace(File inFile, String inKey, String inNewKey) throws Exception
{
FileReader filereader = new FileReader(inFile);
StringWriter out = new StringWriter();
new OutputFiller().fill( filereader, out );
filereader.close();
String readstring = out.toString();
readstring = readstring.replace(inKey, inNewKey );
FileWriter filewriter = new FileWriter(inFile);
new OutputFiller().fill( new StringReader(readstring), filewriter);
filewriter.close();
}
public void copyFiles(InputStream inInputStream, FileOutputStream inFileOutputStream) throws IOException
{
try
{
fieldFiller.fill(inInputStream, inFileOutputStream);
}
finally
{
safeClose(inInputStream);
safeClose(inFileOutputStream);
}
}
public Set getInvalidChars()
{
if (fieldInvalidChars == null)
{
fieldInvalidChars = new HashSet();
fieldInvalidChars.add("?");
fieldInvalidChars.add("*");
fieldInvalidChars.add("\n");
fieldInvalidChars.add("<");
fieldInvalidChars.add(">");
fieldInvalidChars.add(":");
fieldInvalidChars.add("|");
//fieldInvalidChars.add(" \\");
fieldInvalidChars.add(" /");
fieldInvalidChars.add("/ ");
fieldInvalidChars.add("/ ");
fieldInvalidChars.add("(/");
fieldInvalidChars.add("#");
fieldInvalidChars.add("%");
fieldInvalidChars.add("\u00a9");
fieldInvalidChars.add("\u2219");
}
return fieldInvalidChars;
}
/**
* Tests for illegal characters in the input path.
* @param inPath = string to be tested for bad characters
* @return
*/
public boolean isLegalFilename(String inPath)
{
for (Iterator iterator = getInvalidChars().iterator(); iterator.hasNext();)
{
String value=(String) iterator.next();
if(inPath.contains(value))
{
return false;
}
}
//log.info(inPath);
return true;
}
}