
patterntesting.runtime.io.ExtendedFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of patterntesting-rt Show documentation
Show all versions of patterntesting-rt Show documentation
PatternTesting Runtime (patterntesting-rt) is the runtime component for
the PatternTesting framework. It provides the annotations and base classes
for the PatternTesting testing framework (e.g. patterntesting-check,
patterntesting-concurrent or patterntesting-exception) but can be also
used standalone for classpath monitoring or profiling.
It uses AOP and AspectJ to perform this feat.
/*
* $Id: ExtendedFile.java,v 1.15 2016/12/28 21:18:24 oboehm Exp $
*
* Copyright (c) 2014 by Oliver Boehm
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* (c)reated 27.08.2014 by oliver ([email protected])
*/
package patterntesting.runtime.io;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.util.List;
/**
* This is the extended version of the {@link File} class. It provides some
* additional methods which are missing in this class.
*
* @author oliver
* @since 1.5 (27.08.2014)
*/
public final class ExtendedFile extends File {
private static final long serialVersionUID = 20140827L;
private static final Logger LOG = LogManager.getLogger(ExtendedFile.class);
/**
* Instantiates a new extended file.
*
* @param file
* the file
*/
public ExtendedFile(final File file) {
super(file.getPath());
}
/**
* Instantiates a new extended file.
*
* @param filename
* the filename
*/
public ExtendedFile(final String filename) {
super(filename);
}
/**
* Instantiates a new extended file.
*
* @param parent
* the parent
* @param filename
* the filename
*/
public ExtendedFile(final File parent, final String filename) {
super(parent, filename);
}
/**
* Instantiates a new extended file.
*
* @param parent
* the parent
* @param filename
* the filename
*/
public ExtendedFile(final String parent, final String filename) {
super(parent, filename);
}
/**
* Instantiates a new extended file.
*
* @param fileURI
* the file uri
*/
public ExtendedFile(final URI fileURI) {
super(fileURI);
}
/**
* Instantiates a new extended file.
*
* @param parent
* the parent
* @param file
* the file
*/
public ExtendedFile(final File parent, final File file) {
super(parent, file.getPath());
}
/**
* Validates the given file and throws an {@link FileNotFoundException} if
* it is not a valid file. This is the case if
*
* - the file does not exist or
* - the file exists, but is not a file but a directory.
*
*
* If the file does not exist it tr tries guess the real filename. E.g. one
* of the common platform problems is that Windows does not support case
* sensitive filenames whereas Unix platforms distinguish between
* upper/lowercase in filenames. "readme.txt" and "README.TXT" are two
* different files under Unix but not on Windows.
*
*
* @param file the file
* @throws FileNotFoundException the file not found exception
* @since 1.7
*/
public static void validate(File file) throws FileNotFoundException {
if (!file.exists()) {
throw new FileNotFoundException(getMessageForMissing(file));
}
}
private static String getMessageForMissing(File file) {
String msg = "file '" + file + "' does not exist";
File similar = findSimilarFile(file);
if (!similar.getPath().equals(file.getPath())) {
msg += " - do you mean '" + similar + "'?";
}
return msg;
}
private static File findSimilarFile(File file) {
File dir = file.getParentFile();
if (dir == null) {
File currentDir = new File(".");
return new File(findSimilarFilename(currentDir, file.getName()));
} else {
File similarDir = findSimilarFile(dir);
String similarFilename = findSimilarFilename(similarDir, file.getName());
return new File(similarDir, similarFilename);
}
}
private static String findSimilarFilename(File currentDir, String filename) {
String[] currentFiles = currentDir.list();
if (currentFiles != null) {
for (String name : currentFiles) {
if (filename.equalsIgnoreCase(name)) {
LOG.debug("Similar file '{}' for missing '{}' found.", name, filename);
return name;
}
}
}
LOG.trace("No similar '{}' found.", filename);
return filename;
}
/**
* Creates a directory in the temp directory.
*
* @param prefix the prefix
* @param suffix the suffix
* @return the directory
* @throws IOException Signals that an I/O exception has occurred.
*/
public static File createTmpdir(final String prefix, final String suffix) throws IOException {
long n = System.currentTimeMillis();
File tmpdir = getTmpdir(prefix + "@" + Long.toString(n, Character.MAX_RADIX) + suffix);
if (tmpdir.exists()) {
LOG.debug("{} exists already, will increase timestamp.", tmpdir);
tmpdir = getTmpdir(prefix + "@" + Long.toString(n+1, Character.MAX_RADIX) + suffix);
}
if (!tmpdir.mkdirs()) {
throw new IOException("can't create dir " + tmpdir);
}
LOG.trace("Dir {} is created.", tmpdir);
return tmpdir;
}
/**
* Gets the tmpdir.
*
* @param filename the filename
* @return the tmpdir
*/
public static File getTmpdir(final String filename) {
File tmpdir = FileUtils.getTempDirectory();
return new File(tmpdir, filename);
}
/**
* Converts a list with files into a string array.
*
* Since 1.7 this method was moved from the (now deprecated) FileHelper to
* this class here.
*
*
* @param files the files
* @return the string[]
* @since 1.5 (27.08.2014)
*/
public static String[] toStringArray(final List files) {
String[] array = new String[files.size()];
for (int i = 0; i < array.length; i++) {
array[i] = files.get(i).getPath();
}
return array;
}
/**
* Gets the parent as {@link ExtendedFile}. This method was introduced
* because {@link #getParent()} and {@link #getParentFile()} also exists.
*
* @return the parent extended file
*/
public ExtendedFile getParentExtendedFile() {
return new ExtendedFile(this.getParentFile());
}
/**
* Normalizes a file, analogous to {@link FilenameUtils#normalize(String)}.
* But before we normalize it we try to ask to OS for the canonical path for
* it.
*
* @return the normalized file
*/
public File normalize() {
return normalize(this);
}
/**
* Normalizes a file, analogous to {@link FilenameUtils#normalize(String)}.
* But before we normalize it we try to ask to OS for the canonical path for
* it.
*
* @param file the file
* @return the file
*/
public static File normalize(File file) {
String filename = file.getAbsolutePath();
try {
filename = file.getCanonicalPath();
} catch (IOException ex) {
LOG.debug("Cannot get " + file + " as cannocial path:", ex);
}
filename = FilenameUtils.normalize(filename);
return new File(filename);
}
/**
* With this method you can ask if a file ends with the given extension.
*
* @param extension
* the extension - must be a relative path e.g. "WEB-INF/classes"
* @return true, if successful
*/
public boolean endsWith(final File extension) {
assert !extension.isAbsolute() : "not relative: " + extension;
String extensionName = FilenameUtils.normalize(extension.getPath());
String filename = FilenameUtils.normalize(this.getAbsolutePath());
return filename.endsWith(extensionName);
}
/**
* Returns the base of the given file. The 'base' is the given file without
* the extension. Remember, the extension parameter is of type {@link File},
* so it must be a file (not a file extension like ".txt").
*
* @param extension
* the extension - must be a relative path e.g. "WEB-INF/classes"
* @return the file, e.g. "/tmp/web"
*/
public File getBaseDir(final File extension) {
assert !extension.isAbsolute() : "not relative: " + extension;
if (extension.getName().equals(this.getName())) {
File extensionParent = extension.getParentFile();
if (extensionParent == null) {
return this.getParentExtendedFile();
} else {
return this.getParentExtendedFile().getBaseDir(extensionParent);
}
}
LOG.debug("Base dir is '{}' because '{}' does not end with '{}'.", this, extension, this.getName());
return this;
}
/**
* Creates the output stream of the file. As fallback stdout will
* be used if the output stream cannot be created.
*
* @param file the file
* @return the output stream
* @since 1.7
*/
public static OutputStream createOutputStreamFor(File file) {
if (file.exists()) {
if (file.delete()) {
LOG.info("Old file \"{}\" was deleted.", file);
} else {
LOG.warn("Old log file \"{}\" could not be deleted!", file);
}
}
try {
return new BetterFileOutputStream(file, true);
} catch (FileNotFoundException fnfe) {
LOG.debug("Cannot log to {}:", file, fnfe);
LOG.info("Will log to stdout because cannot log to \"{}\" ({}).", file, fnfe.getMessage());
return System.out;
}
}
/**
* Creates the output stream of the file. As fallback stdout will
* be used if the output stream cannot be created.
*
* @return the output stream
* @since 1.7
*/
public OutputStream createOutputStream() {
return createOutputStreamFor(this);
}
/**
* Comparing two files is not so easy as it seems to be. On unix systems or
* Mac OS-X you can see the same file via two different mount points or as
* two different hard links. If you are on *nix you can use the inode to
* compare but how to get the inode?
*
* @param obj the other file
* @return true, if successful
* @see java.io.File#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (!(obj instanceof File)) {
return false;
}
File otherFile = normalize((File) obj);
File thisFile = this.normalize();
return thisFile.getPath().equals(otherFile.getPath());
}
/**
* Hash code.
*
* @return the int
* @see java.io.File#hashCode()
*/
@Override
public int hashCode() {
return this.normalize().hashCode();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy