ArchivingFileManager.java
package org.jbehave.io;
import static java.util.Arrays.asList;
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.io.FilenameUtils;
/**
* File manager that uploads and unarchives data files
*/
public class ArchivingFileManager implements FileManager {
final FileArchiver archiver;
final FileMonitor monitor;
private final File uploadDirectory;
public ArchivingFileManager(FileArchiver archiver, FileMonitor monitor, File uploadDirectory) {
this.archiver = archiver;
this.monitor = monitor;
this.uploadDirectory = uploadDirectory;
}
public List<File> list() {
File directory = uploadDirectory();
List<File> files = asList(directory.listFiles(new FileFilter() {
public boolean accept(File file) {
return !file.isDirectory();
}
}));
monitor.filesListed(directory, files);
return files;
}
File uploadDirectory() {
uploadDirectory.mkdirs();
return uploadDirectory;
}
public List<File> listContent(File file, boolean relativePaths) {
if (!archiver.isArchive(file)) {
return asList(file);
}
File directory = new File(uploadDirectory, archiver.directoryOf(new File(file.getName())).getPath());
List<File> content = new ArrayList<File>();
for (File archiveFile : archiver.listContent(directory)) {
File contentFile = (relativePaths ? archiver.relativeTo(archiveFile, directory) : archiveFile);
content.add(contentFile);
}
monitor.contentListed(file.getPath(), directory, relativePaths, content);
return content;
}
public void delete(List<File> files) {
for (File file: files) {
deleteFile(file);
}
}
private void deleteFile(File file) {
if (file.isDirectory()) {
// recursively delete children
for (String child : file.list()) {
deleteFile(new File(file, child));
}
}
if (archiver.isArchive(file)) {
// delete the unarchived directory too
File directory = archiver.directoryOf(file);
deleteFile(directory);
monitor.fileDeleted(directory);
}
file.delete();
monitor.fileDeleted(file);
}
public List<File> upload(List<FileItem> fileItems, List<String> errors) {
List<File> files = new ArrayList<File>();
File directory = uploadDirectory();
for (FileItem item : fileItems) {
try {
File file = writeItemToFile(directory, item);
monitor.fileUploaded(file);
files.add(file);
} catch (FileItemNameMissingException e) {
// ignore and carry on
} catch (FileWriteFailedException e) {
errors.add(e.getMessage());
if (e.getCause() != null) {
errors.add(e.getCause().getMessage());
}
monitor.fileUploadFailed(item, e);
}
}
return files;
}
public void unarchiveFiles(List<File> files, List<String> errors) {
File directory = uploadDirectory();
for (File file : files) {
if (archiver.isArchive(file)) {
try {
archiver.unarchive(file, directory);
monitor.fileUnarchived(file, directory);
} catch (FileUnarchiveFailedException e) {
errors.add(e.getMessage());
if (e.getCause() != null) {
errors.add(e.getCause().getMessage());
}
}
}
}
}
private File writeItemToFile(File directory, FileItem item) {
if (isBlank(item.getName())) {
throw new FileItemNameMissingException(item);
}
File file = new File(directory, fileName(item));
try {
if (file.exists()) {
file.createNewFile();
}
item.write(file);
} catch (Exception e) {
throw new FileWriteFailedException(file, e);
}
return file;
}
private String fileName(FileItem item) {
// FileItem.getName() may return the full path, depending on the client
// (e.g. IE or Opera)
// FilenameUtils.getName(path) extracts file name whatever the path
// separator (Unix or Windows)
return FilenameUtils.getName(item.getName());
}
public File getUploadDirectory() {
return uploadDirectory;
}
@SuppressWarnings("serial")
public static final class FileItemNameMissingException extends RuntimeException {
public FileItemNameMissingException(FileItem file) {
super(file.toString() + " missing name");
}
}
@SuppressWarnings("serial")
public static final class FileWriteFailedException extends RuntimeException {
public FileWriteFailedException(File file, Throwable cause) {
super(file.toString() + " write failed", cause);
}
}
}