/**
* Copyright (C) 2008-2010, Squale Project - http://www.squale.org
*
* This file is part of Squale.
*
* Squale 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 3 of the
* License, or any later version.
*
* Squale 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 Lesser General Public License
* along with Squale. If not, see <http://www.gnu.org/licenses/>.
*/
package org.squale.squalix.util.file;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.BUnzip2;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.taskdefs.GUnzip;
import org.apache.tools.ant.taskdefs.Untar;
/**
* Utilitaire pour les fichiers compress�s Le type d'archive est connu en ex�cutant la commande 'file' d'unix. Dans le
* cas o� cette commande �chouerait (si l'ex�cution se fait sous windows par exemple), on reconnait le type gr�ce �
* l'extension du fichier.
*/
public class ZipFileUtility
{
// R�sultat renvoy� par la commande 'file' d'unix
/** R�sultat pour les archives tar posix */
public static final String POSIX_TAR_RESULT = "POSIX tar archive";
/** R�sultat pour les archives tar */
public static final String TAR_RESULT = "USTAR tar archive";
/** R�sultat pour les fichiers zipp�s avec GZip */
public static final String GZIP_RESULT = "gzip compressed data";
/** R�sultat pour les fichiers zipp�s avec BZip2 */
public static final String BZIP2_RESULT = "bzip2 compressed data";
/** R�sultat pour une archive zip */
public static final String ZIP_RESULT = "ZIP archive";
/** R�sultat pour une archive jar */
public static final String JAR_RESULT = "java program";
/** R�sultats d'archives */
public static final String[] ARCHIVE_RESULTS =
{ POSIX_TAR_RESULT, TAR_RESULT, GZIP_RESULT, BZIP2_RESULT, ZIP_RESULT, JAR_RESULT };
// Dans le cas o� la commande file �choue, on utilisera les extensions du fichier
/** Extension d'une archive tar */
public static final String TAR_EXTENSION = ".tar";
/** Extension d'une archive jar */
public static final String JAR_EXTENSION = ".jar";
/** Extension d'une archive GZip */
public static final String GZIP_EXTENSION = ".gz";
/** Extension d'une archive BZip2 */
public static final String BZIP2_EXTENSION = ".bz2";
/** Extension d'une archive zip */
public static final String ZIP_EXTENSION = ".zip";
/** Extension d'une archive ear */
public static final String EAR_EXTENSION = ".ear";
/** Extension d'une archive war */
public static final String WAR_EXTENSION = ".war";
/** Extension d'une archive targz */
public static final String TGZ_EXTENSION = ".tgz"; // car courante
/** Extensions d'archives reconnues */
public static final String[] ARCHIVE_EXTENSIONS =
{ TAR_EXTENSION, JAR_EXTENSION, GZIP_EXTENSION, BZIP2_EXTENSION, ZIP_EXTENSION, EAR_EXTENSION, WAR_EXTENSION,
TGZ_EXTENSION };
/**
* Extrait les fichiers et r�pertoires contenus dans pArchive dans le r�pertoire de destination pDest PRECONDITION :
* pArchive et pDest existent
*
* @param pArchive l'archive � d�compresser
* @param pDest le r�pertoire de destination
* @throws Exception si erreur
*/
public static void extractArchiveFile( File pArchive, File pDest )
throws Exception
{
// On va appeler diff�rentes m�thodes en fonction du type de l'archive
// On r�cup�re le type de pSrc avec la commande unix "file"
// On traite � part le cas des .tgz car commande courante mais pas m�me traitement
String archiveType = getExtension( pArchive.getName() );
if ( !archiveType.equalsIgnoreCase( TGZ_EXTENSION ) )
{
archiveType = isArchiveFile( pArchive );
}
if ( !( "" ).equals( archiveType ) )
{
// On extrait l'archive
extractArchiveFile( pArchive, pDest, archiveType );
}
}
/**
* Extrait les fichiers et r�pertoires contenus dans pArchive dans le r�pertoire de destination pDest PRECONDITION :
* pArchive et pDest existent
*
* @param pArchive l'archive � d�compresser
* @param pDest le r�pertoire de destination
* @param pArchiveType le r�sulat de la commande 'file' d'unix
* @throws Exception si erreur
*/
public static void extractArchiveFile( File pArchive, File pDest, String pArchiveType )
throws Exception
{
// En fonction du type d'archive, on utilise la t�che ant appropri�e
if ( isZipFile( pArchiveType ) )
{
// .zip
unZip( pArchive, pDest );
}
else if ( isTarFile( pArchiveType ) )
{
// .tar
extractTarFile( pArchive, pDest );
}
else if ( isGZipFile( pArchiveType ) )
{
// .gz
unGZip( pArchive, pDest );
}
else if ( isBZip2File( pArchiveType ) )
{
// .bz2
unBZip2( pArchive, pDest );
}
else
{
// cas o� l'archive n'est pas g�r� par SQUALE
String message = FileMessages.getString( "exception.not_archive_file", pArchive.getAbsolutePath() );
throw new IOException( message );
}
// On r�cup�re le r�pertoire de d'extraction
File destFile = getDestFile( pDest, pArchive.getName() );
// On supprime l'archive que l'on vient d'extraire car on en a plus besoin
// si pDest est un parent
File newArchive = pArchive;
if ( newArchive.getAbsolutePath().startsWith( pDest.getAbsolutePath() ) )
{
newArchive.delete();
}
newArchive = destFile;
// car par exemple d'un .tar.gz
extractArchiveFile( newArchive, pDest );
}
/**
* @param pArchiveType le r�sultat de la commande file ou l'extension de l'archive
* @return si il s'agit d'une archive � d�zipper avec la m�thode <code>extractZipFile</code>
*/
private static boolean isZipFile( String pArchiveType )
{
// Dans le cas de la commande file
boolean result = pArchiveType.lastIndexOf( ZIP_RESULT ) != -1 || pArchiveType.lastIndexOf( JAR_RESULT ) != -1;
// Dans le cas des extensions
result =
result || pArchiveType.equalsIgnoreCase( ZIP_EXTENSION ) || pArchiveType.equalsIgnoreCase( EAR_EXTENSION )
|| pArchiveType.equalsIgnoreCase( WAR_EXTENSION ) || pArchiveType.equalsIgnoreCase( JAR_EXTENSION );
return result;
}
/**
* @param pArchiveType le r�sultat de la commande file ou l'extension de l'archive
* @return si il s'agit d'une archive compress�e avec BZip2
*/
private static boolean isBZip2File( String pArchiveType )
{
// Dans le cas de la commande file
boolean result = pArchiveType.lastIndexOf( BZIP2_RESULT ) != -1;
// Dans le cas des extensions
result = result || pArchiveType.equalsIgnoreCase( BZIP2_EXTENSION );
return result;
}
/**
* @param pArchiveType le r�sultat de la commande file ou l'extension de l'archive
* @return si il s'agit d'une archive compress�e avec GZip
*/
private static boolean isGZipFile( String pArchiveType )
{
// Dans le cas de la commande file
boolean result = pArchiveType.lastIndexOf( GZIP_RESULT ) != -1;
// Dans le cas des extensions
result = result || pArchiveType.equalsIgnoreCase( GZIP_EXTENSION );
return result;
}
/**
* @param pArchiveType le r�sultat de la commande file ou l'extension de l'archive
* @return si il s'agit d'une archive tar
*/
private static boolean isTarFile( String pArchiveType )
{
// Dans le cas de la commande file
boolean result =
pArchiveType.lastIndexOf( TAR_RESULT ) != -1 || pArchiveType.lastIndexOf( POSIX_TAR_RESULT ) != -1;
// Dans le cas des extensions on consid�re aussi que le .tgz est un tar
// car on va utiliser untar avec l'option de d�compression
result =
result || pArchiveType.equalsIgnoreCase( TAR_EXTENSION ) || pArchiveType.equalsIgnoreCase( TGZ_EXTENSION );
;
return result;
}
/**
* @param pZip le fichier � d�zipper
* @param pDest le r�pertoire de destination
*/
private static void unZip( File pZip, File pDest )
{
Expand expander = new Expand();
expander.setProject( new Project() );
expander.init();
expander.setSrc( pZip );
expander.setDest( pDest );
expander.execute();
}
/**
* @param pZip le fichier � d�zipper
* @param pDest le r�pertoire de destination
*/
private static void unBZip2( File pZip, File pDest )
{
BUnzip2 unzip = new BUnzip2();
unzip.setProject( new Project() );
unzip.init();
unzip.setDest( pDest );
unzip.setSrc( pZip );
unzip.execute();
}
/**
* @param pZip le fichier � d�zipper
* @param pDest le r�pertoire de destination
*/
private static void unGZip( File pZip, File pDest )
{
GUnzip unzip = new GUnzip();
unzip.setProject( new Project() );
unzip.init();
unzip.setDest( pDest );
unzip.setSrc( pZip );
unzip.execute();
}
/**
* @param pTar le tar � d�compresser
* @param pDest le r�pertoire de destination
*/
private static void extractTarFile( File pTar, File pDest )
{
Untar untar = new Untar();
untar.setProject( new Project() );
untar.init();
untar.setDest( pDest );
untar.setSrc( pTar );
// cas sp�cial d'un .tgz
if ( getExtension( pTar.getName() ).equalsIgnoreCase( TGZ_EXTENSION ) )
{
Untar.UntarCompressionMethod mode = new Untar.UntarCompressionMethod();
mode.setValue( "gzip" );
untar.setCompression( mode );
}
untar.execute();
}
/**
* @param pParentFile le fichier parent
* @param pFileName le nom du fichier
* @return le fichier extrait
*/
private static File getDestFile( File pParentFile, String pFileName )
{
String destFileName = getFileNameWithoutExtension( pFileName );
File pDestFile = new File( pParentFile, destFileName );
return pDestFile;
}
/**
* @param pFileName le nom du fichier
* @return le nom du fichier sans son extension si extesion il y a
*/
private static String getFileNameWithoutExtension( String pFileName )
{
String filename = pFileName;
int lastDot = pFileName.lastIndexOf( "." );
if ( lastDot != -1 )
{
filename = pFileName.substring( 0, lastDot );
}
return filename;
}
/**
* @param pFile le fichier � v�rifier
* @return l'ex�cution de la commande "type" d'unix si pFile est une archive une cha�ne vide sinon.
* @throws IOException si erreur de flux
* @throws InterruptedException si erreur lors du lancement de la commande file d'unix
*/
public static String isArchiveFile( File pFile )
throws IOException, InterruptedException
{
String cmdResult = "";
Runtime runtime = Runtime.getRuntime();
// On utilise la commande unix "file" pour conna�tre le type d'un fichier
String cmd = "file " + pFile.getAbsolutePath();
try
{
Process process = runtime.exec( cmd );
process.waitFor();
// On r�cup�re le r�sultat
InputStream cmdInput = process.getInputStream();
int reader;
while ( ( reader = cmdInput.read() ) != -1 )
{
cmdResult += (char) reader;
}
cmdInput.close();
boolean isArchive = false;
// C'est une archive si le type est pr�sent dans les types r�pertori�s
// dans le tableau de constantes ARCHIVE_RESULTS
for ( int i = 0; i < ARCHIVE_RESULTS.length && !isArchive; i++ )
{
if ( cmdResult.lastIndexOf( ARCHIVE_RESULTS[i] ) != -1 )
{
isArchive = true;
}
}
// Si il ne s'agit pas d'une archive, on retourne una cha�ne vide
if ( !isArchive )
{
cmdResult = "";
}
}
catch ( IOException ioe )
{
cmdResult = "";
}
// si la commande n'est pas ex�cut�e avec succ�s ou qu'on n'a pas trouv� l'extension
// on recherche l'extension par le nom du fichier
// Le r�sulat sera alors l'extension du fichier
// ou vide si le fichier n'a pas d'extension ou si l'extension n'est pas reconnu
if ( cmdResult.length() == 0 )
{
cmdResult = getExtension( pFile.getName() );
if ( !isKnownExtension( cmdResult ) )
{
cmdResult = "";
}
}
return cmdResult;
}
/**
* @param pExtension l'extension � v�rifier
* @return true si l'extension est reconnue comme �tant l'extension d'une archive
*/
private static boolean isKnownExtension( String pExtension )
{
boolean isKnown = false;
for ( int i = 0; i < ARCHIVE_EXTENSIONS.length && !isKnown; i++ )
{
if ( pExtension.equalsIgnoreCase( ARCHIVE_EXTENSIONS[i] ) )
{
isKnown = true;
}
}
return isKnown;
}
/**
* @param pFilename le nom du fichier
* @return l'extension si elle existe
*/
private static String getExtension( String pFilename )
{
String extension = "";
int lastDot = pFilename.lastIndexOf( "." );
if ( lastDot > 0 )
{
extension = pFilename.substring( lastDot );
}
return extension;
}
}