/**
* This file is part of Waarp Project.
*
* Copyright 2009, Frederic Bregier, and individual contributors by the @author tags. See the
* COPYRIGHT.txt in the distribution for a full listing of individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* Waarp 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 General Public License along with Waarp . If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.waarp.common.tar;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;
/**
* TAR support
*
* @author Frederic Bregier
*
*/
public class TarUtility {
/**
* Create a new Tar from a root directory
*
* @param directory
* the base directory
* @param filename
* the output filename
* @param absolute
* store absolute filepath (from directory) or only filename
* @return True if OK
*/
public static boolean createTarFromDirectory(String directory, String filename, boolean absolute) {
File rootDir = new File(directory);
File saveFile = new File(filename);
// recursive call
TarArchiveOutputStream taos;
try {
taos = new TarArchiveOutputStream(new FileOutputStream(saveFile));
} catch (FileNotFoundException e) {
return false;
}
taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
try {
recurseFiles(rootDir, rootDir, taos, absolute);
} catch (IOException e2) {
try {
taos.close();
} catch (IOException e) {
// ignore
}
return false;
}
try {
taos.finish();
} catch (IOException e1) {
// ignore
}
try {
taos.flush();
} catch (IOException e) {
// ignore
}
try {
taos.close();
} catch (IOException e) {
// ignore
}
return true;
}
/**
* Recursive traversal to add files
*
* @param root
* @param file
* @param taos
* @param absolute
* @throws IOException
*/
private static void recurseFiles(File root, File file, TarArchiveOutputStream taos,
boolean absolute) throws IOException {
if (file.isDirectory()) {
// recursive call
File[] files = file.listFiles();
for (File file2 : files) {
recurseFiles(root, file2, taos, absolute);
}
} else if ((!file.getName().endsWith(".tar")) && (!file.getName().endsWith(".TAR"))) {
String filename = null;
if (absolute) {
filename = file.getAbsolutePath().substring(root.getAbsolutePath().length());
} else {
filename = file.getName();
}
TarArchiveEntry tae = new TarArchiveEntry(filename);
tae.setSize(file.length());
taos.putArchiveEntry(tae);
FileInputStream fis = new FileInputStream(file);
IOUtils.copy(fis, taos);
taos.closeArchiveEntry();
}
}
/**
* Create a new Tar from a list of Files (only name of files will be used)
*
* @param files
* list of files to add
* @param filename
* the output filename
* @return True if OK
*/
public static boolean createTarFromFiles(List<File> files, String filename) {
return createTarFromFiles(files.toArray(new File[] {}), filename);
}
/**
* Create a new Tar from an array of Files (only name of files will be used)
*
* @param files
* array of files to add
* @param filename
* the output filename
* @return True if OK
*/
public static boolean createTarFromFiles(File[] files, String filename) {
File saveFile = new File(filename);
// recursive call
TarArchiveOutputStream taos;
try {
taos = new TarArchiveOutputStream(new FileOutputStream(saveFile));
} catch (FileNotFoundException e) {
return false;
}
taos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
for (File file : files) {
try {
addFile(file, taos);
} catch (IOException e) {
try {
taos.close();
} catch (IOException e1) {
// ignore
}
return false;
}
}
try {
taos.finish();
} catch (IOException e1) {
// ignore
}
try {
taos.flush();
} catch (IOException e) {
// ignore
}
try {
taos.close();
} catch (IOException e) {
// ignore
}
return true;
}
/**
* Recursive traversal to add files
*
* @param file
* @param taos
* @throws IOException
*/
private static void addFile(File file, TarArchiveOutputStream taos) throws IOException {
String filename = null;
filename = file.getName();
TarArchiveEntry tae = new TarArchiveEntry(filename);
tae.setSize(file.length());
taos.putArchiveEntry(tae);
FileInputStream fis = new FileInputStream(file);
IOUtils.copy(fis, taos);
taos.closeArchiveEntry();
}
/**
* Extract all files from Tar into the specified directory
*
* @param tarFile
* @param directory
* @return the list of extracted filenames
* @throws IOException
*/
public static List<String> unTar(File tarFile, File directory) throws IOException {
List<String> result = new ArrayList<String>();
InputStream inputStream = new FileInputStream(tarFile);
TarArchiveInputStream in = new TarArchiveInputStream(inputStream);
try {
TarArchiveEntry entry = in.getNextTarEntry();
while (entry != null) {
if (entry.isDirectory()) {
entry = in.getNextTarEntry();
continue;
}
File curfile = new File(directory, entry.getName());
File parent = curfile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
OutputStream out = new FileOutputStream(curfile);
try {
IOUtils.copy(in, out);
} finally {
out.close();
}
result.add(entry.getName());
entry = in.getNextTarEntry();
}
} finally {
in.close();
}
return result;
}
public static void main(String[] args) {
if (args.length < 3) {
System.err.println("You need to provide 3 arguments:\n" +
" option filedest.tar \"source\"\n" +
" where option=1 means untar and source is a directory\n" +
" option=2 means tar and source is a directory\n" +
" option=3 means tar and source is a list of files comma separated");
System.exit(1);
}
int option = Integer.parseInt(args[0]);
String tarfile = args[1];
String tarsource = args[2];
String[] tarfiles = null;
if (option == 3) {
tarfiles = args[2].split(",");
File[] files = new File[tarfiles.length];
for (int i = 0; i < tarfiles.length; i++) {
files[i] = new File(tarfiles[i]);
}
if (createTarFromFiles(files, tarfile)) {
System.out.println("TAR OK from multiple files");
} else {
System.err.println("TAR KO from multiple files");
}
} else if (option == 2) {
if (createTarFromDirectory(tarsource, tarfile, false)) {
System.out.println("TAR OK from directory");
} else {
System.err.println("TAR KO from directory");
}
} else if (option == 1) {
File tarFile = new File(tarfile);
File directory = new File(tarsource);
List<String> result = null;
try {
result = unTar(tarFile, directory);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (result == null || result.isEmpty()) {
System.err.println("UNTAR KO from directory");
} else {
for (String string : result) {
System.out.println("File: " + string);
}
}
}
}
}