net.sf.xsltmp.util.UnArchiverHelper Maven / Gradle / Ivy
package net.sf.xsltmp.util;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
/**
* Gets files from archives.
*
* Maintains a repository of all extracted files in a given directory. The
* repository is organized by the archive name and the path of the files within
* the archives.
*
* When a file has already been extracted previously, it is served from the
* repository and not extracted again.
*
* When it is not present in the repository, extracts it from the archive to the
* repository based on the requested file path within the archive and then
* serves it from the repository.
*
* Once a file has been extracted from a given archive, remembers the path of
* the file within the archive. Subsequent requests for files within the same
* archive may specify the path relative to the path of the last request.
*/
public class UnArchiverHelper {
/**
* Maven log.
*/
private final Log log;
/**
* Maven project.
*/
private final MavenProject project;
/**
* Plexus archiver manager.
*/
private final ArchiverManager archiverManager;
/**
* The directory of the repository of extracted files.
*/
private final File commonExtractDir;
/**
* Map of previous valid paths within archives.
*/
private final Map> archiveValidSubdirs;
/**
* Constructor.
*
* @param log
* Maven log
* @param project
* Maven project
* @param archiverManager
* Plexus archiver manager
* @param commonExtractDir
* The directory of the repository of extracted files
*/
public UnArchiverHelper(Log log, MavenProject project,
ArchiverManager archiverManager, String commonExtractDir) {
this.log = log;
this.project = project;
this.archiverManager = archiverManager;
this.commonExtractDir = new File(
getProject().getBuild().getDirectory(), commonExtractDir);
archiveValidSubdirs = new HashMap>();
}
public Log getLog() {
return log;
}
public MavenProject getProject() {
return project;
}
public ArchiverManager getArchiverManager() {
return archiverManager;
}
public File getCommonExtractDir() {
return commonExtractDir;
}
public Map> getArchiveValidSubdirs() {
return archiveValidSubdirs;
}
/**
* Get a file from an archive.
*
* @param archive
* The archive file
* @param filePath
* Relative path to the file within the archive
* @return File The file from the archive
*/
public File getFile(File archive, String filePath) {
if (getLog().isDebugEnabled())
getLog().debug("Getting: " + filePath + " from archive: " + archive);
File extractDir = getExtractDir(archive);
// was already extracted?
File result = new File(extractDir, filePath);
if (!result.exists()) {
extract(archive, filePath);
if (!result.exists()) {
// extracting from received file path does not work
// ==> try extracting from previous valid path dirs
for (Iterator iterator = getArchiveSubdirs(archive)
.iterator(); iterator.hasNext();) {
String subdir = iterator.next();
String newFilePath = new File(subdir, filePath).getPath();
extract(archive, newFilePath);
result = new File(extractDir, newFilePath);
}
} else {
// extracting from received file path worked
// ==> store the valid path for future use
storeValidSubdir(archive, filePath);
}
}
return result;
}
private void storeValidSubdir(File archive, String filePath) {
String subdir = new File(filePath).getParent();
getArchiveSubdirs(archive).add(subdir);
if (getLog().isDebugEnabled())
getLog().debug(
"Storing last valid subdir for archive: "
+ archive.getName() + " as: " + subdir);
}
private HashSet getArchiveSubdirs(File archive) {
HashSet set = getArchiveValidSubdirs().get(archive.getName());
if (null == set) {
set = new HashSet();
getArchiveValidSubdirs().put(archive.getName(), set);
}
return set;
}
/**
* Extract a file from an archive.
*
* @param archive
* The archive file
* @param filePath
* Relative path to the file to be extracted within the archive
*/
public void extract(File archive, String filePath) {
File extractDir = getExtractDir(archive);
if (getLog().isDebugEnabled())
getLog().debug(
"Extracting: " + filePath + " from: " + archive + " to: "
+ extractDir);
extractDir.mkdirs();
try {
UnArchiver unArchiver;
unArchiver = getArchiverManager().getUnArchiver(archive);
unArchiver.setSourceFile(archive);
unArchiver.setDestDirectory(extractDir);
IncludeExcludeFileSelector[] selectors = new IncludeExcludeFileSelector[] { new IncludeExcludeFileSelector() };
selectors[0].setIncludes(new String[] { filePath });
unArchiver.setFileSelectors(selectors);
unArchiver.extract();
} catch (NoSuchArchiverException e) {
getLog().warn("Unknown archiver type.");
} catch (ArchiverException e) {
getLog().warn(
"Error unpacking file: " + archive + "\t" + e.toString());
}
}
/**
* Return the extract dir for an archive
*
* @param archive
* The archive file
* @return File The directory to where files from the archive should be
* extracted
*/
private File getExtractDir(File archive) {
return new File(commonExtractDir, archive.getName());
}
}