Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* de.unkrig.commons - A general-purpose Java class library
*
* Copyright (c) 2011, Arno Unkrig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package de.unkrig.commons.file.filetransformation;
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.util.Comparator;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.CompressorInputStream;
import de.unkrig.commons.file.CompressUtil;
import de.unkrig.commons.file.CompressUtil.ArchiveHandler;
import de.unkrig.commons.file.CompressUtil.CompressorHandler;
import de.unkrig.commons.file.CompressUtil.NormalContentsHandler;
import de.unkrig.commons.file.ExceptionHandler;
import de.unkrig.commons.file.FileUtil;
import de.unkrig.commons.file.contentstransformation.ContentsTransformations;
import de.unkrig.commons.file.contentstransformation.ContentsTransformer;
import de.unkrig.commons.file.org.apache.commons.compress.archivers.ArchiveFormat;
import de.unkrig.commons.file.org.apache.commons.compress.compressors.CompressionFormat;
import de.unkrig.commons.io.IoUtil;
import de.unkrig.commons.lang.AssertionUtil;
import de.unkrig.commons.lang.protocol.ConsumerWhichThrows;
import de.unkrig.commons.lang.protocol.Predicate;
import de.unkrig.commons.nullanalysis.Nullable;
import de.unkrig.commons.text.pattern.Glob;
/**
* Various {@link FileTransformer}-related utility methods.
*
* A typical application is to wrap file transformers and content transformers as follows:
*
*
* |
* v
* directoryTreeTransformer()
* |
* v
* recursiveCompressedAndArchiveFileTransformer()
* |
* v
* (some contents fransformer, e.g. 'ContentsTransformerUtil.NOP')
*
*
* The {@link #directoryTreeTransformer(Comparator, Predicate, Glob, DirectoryCombiner, FileTransformer, boolean,
* boolean, ExceptionHandler) directoryTreeTransformer())} can be left out if you don't need recursive directory
* traversal.
*
*
* The {@link #recursiveCompressedAndArchiveFileTransformer(Predicate, Predicate, Glob, ArchiveCombiner,
* ContentsTransformer, boolean, ExceptionHandler) recursiveCompressedAndArchiveFileTransformer()} can be left out if
* you don't want to look into archives nor compressed files.
*
*/
public final
class FileTransformations {
static { AssertionUtil.enableAssertionsForThisClass(); }
/**
* If in equals out ("in-place transformation"), then file in is deleted. Otherwise
* ("out-of-place transformation") nothing is done, i.e. a file out is not created.
*/
public static FileTransformer
remove() {
return new FileTransformer() {
@Override public void
transform(String path, File in, File out, Mode mode) throws IOException {
switch (mode) {
case CHECK:
throw FileTransformer.NOT_IDENTICAL;
case CHECK_AND_TRANSFORM:
throw AssertionUtil.fail("Must not invoke 'remove()' in mode CHECK_AND_TRANSFORM");
case TRANSFORM:
if (in.equals(out)) {
if (!in.delete()) throw new IOException("Could not delete '" + in + "'");
}
return;
default:
throw AssertionUtil.fail("Unexpected mode '" + mode + "'");
}
}
};
}
/**
* If in equals out ("in-place transformation"), then file is left untouched. Otherwise
* ("out-of-place transformation") in is copied byte-by-byte to out.
*/
public static final FileTransformer
UNCHANGED = new FileTransformer() {
@Override public void
transform(String path, File in, File out, Mode mode) throws IOException {
switch (mode) {
case CHECK:
return;
case CHECK_AND_TRANSFORM:
case TRANSFORM:
if (!in.equals(out)) IoUtil.copy(in, out);
return;
default:
throw AssertionUtil.fail("Unexpected mode '" + mode + "'");
}
}
};
private
FileTransformations() {}
/**
* @see DirectoryCombiner#combineDirectory(String, ConsumerWhichThrows)
* @see ArchiveCombiner#combineArchive(String, ConsumerWhichThrows)
*/
public
interface NameAndContents {
/** @return A simple name (must not contain separators) */
String getName();
/**
* @return A stream producing the contents
* @throws FileNotFoundException
*/
InputStream open() throws FileNotFoundException;
}
/** @see #combineDirectory(String, ConsumerWhichThrows) */
public
interface DirectoryCombiner {
/**
* Is invoked after the members of the directory have been transformed.
*
* The name of the interface and this method is historical; actually nothing is "combined".
*
*
* @param directoryPath The path designating the directory being transformed
* @param memberAdder Can be called to add members to the output directory
*/
void
combineDirectory(
String directoryPath,
ConsumerWhichThrows super NameAndContents, ? extends IOException> memberAdder
) throws IOException;
/**
* An {@link DirectoryCombiner} that does nothing.
*/
DirectoryCombiner NOP = new DirectoryCombiner() {
@Override public void
combineDirectory(
String directoryPath,
ConsumerWhichThrows super NameAndContents, ? extends IOException> memberAdder
) {}
};
}
/** @see #combineArchive(String, ConsumerWhichThrows) */
public
interface ArchiveCombiner {
/**
* Combines the results of {@link ContentsTransformer#transform(String, InputStream, java.io.OutputStream)}
* for all archive entries into one object.
*
* @param archivePath The path designating the archive being transformed
* @param entryAdder Can be called to add entries to the archive
*/
void
combineArchive(
String archivePath,
ConsumerWhichThrows super NameAndContents, ? extends IOException> entryAdder
) throws IOException;
/**
* An {@link ArchiveCombiner} that does nothing.
*/
ArchiveCombiner NOP = new ArchiveCombiner() {
@Override public void
combineArchive(
String archivePath,
ConsumerWhichThrows super NameAndContents, ? extends IOException> entryAdder
) {}
};
}
/**
* Creates and returns a {@link DirectoryTransformer} which implements the following features:
*
*
Recursive processing of directories
*
Removal, renaming and addition of directory members
*
*
* @param directoryMemberNameComparator The comparator used to sort a directory's members; a {@code null} value
* means to NOT sort the members, i.e. leave them in their 'natural' order as
* {@link File#list()} returns them
* @param directoryMemberRemoval Whether to remove (i.e. not copy) a member; the subject is the path of the
* member
* @param directoryMemberRenaming {@link Glob#replace(String) Transforms the name} of a member
* @param saveSpace If {@code true}, then the method attempts to save file system space for
* in-place transformations by transforming each file, otherwise it
* creates a copy of the entire directory tree before deleting the original
*/
public static DirectoryTransformer
directoryTreeTransformer(
@Nullable Comparator