/*
* Copyright 1998-2014 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "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 UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package thredds.util.filesource;
import org.springframework.util.StringUtils;
import java.io.File;
/**
* _more_
*
* @author edavis
* @since 4.0
*/
public class BasicDescendantFileSource implements DescendantFileSource {
//private static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BasicDescendantFileSource.class);
private final String rootDirectoryPath;
private final File rootDirectory;
public BasicDescendantFileSource(File rootDirectory) {
if (rootDirectory == null)
throw new IllegalArgumentException("Root directory must not be null.");
if (!rootDirectory.exists())
throw new IllegalArgumentException("Root directory must exist: " + rootDirectory.getAbsolutePath() + ".");
if (!rootDirectory.isDirectory())
throw new IllegalArgumentException("Root directory must be a directory: " + rootDirectory.getAbsolutePath() + ".");
this.rootDirectoryPath = StringUtils.cleanPath(rootDirectory.getAbsolutePath());
this.rootDirectory = new File(this.rootDirectoryPath);
}
public BasicDescendantFileSource(String rootDirectoryPath) {
if (rootDirectoryPath == null)
throw new IllegalArgumentException("Root directory must not be null.");
File file = new File(rootDirectoryPath);
if (!file.exists())
throw new IllegalArgumentException("Root directory must exist: " + rootDirectoryPath + ".");
if (!file.isDirectory())
throw new IllegalArgumentException("Root directory must be a directory: " + rootDirectoryPath + ".");
this.rootDirectoryPath = StringUtils.cleanPath(file.getAbsolutePath());
this.rootDirectory = new File(this.rootDirectoryPath);
}
/**
* This implementation requires the path to be relative to the root
* directory and a descendant of the root directory. It also requires the
* relative path at each path segment to be a descendant of the root
* directory, i.e., it cannot start with "../" or contain "../" path
* segments such that once "normalized" it would start with "../"
* (e.g., "dir1/../../dir2" once normalized would be "../dir2").
*
* @param path the relative path to the descendant File.
* @return the descendant File represented by the given relative path or null if the path is null, not relative to the root, not a descendant, or the File doesn't exist.
*/
public File getFile(String path) {
if (path == null)
return null;
String workPath = StringUtils.cleanPath(path);
if (workPath.startsWith("../"))
return null;
if (new File(workPath).isAbsolute())
return null;
File file = new File(this.rootDirectory, workPath);
if (file.exists())
return file;
else
return null;
}
public DescendantFileSource getDescendant(String relativePath) {
File descendantFile = getFile(relativePath);
if (descendantFile == null || !descendantFile.isDirectory())
return null;
return new BasicDescendantFileSource(descendantFile);
}
public File getRootDirectory() {
return this.rootDirectory;
}
public String getRootDirectoryPath() {
return this.rootDirectoryPath;
}
public boolean isDescendant(File file) {
if (file == null)
return false;
String relPath = getRelativePath(file);
return !(relPath == null || relPath.equals(""));
}
public boolean isDescendant(String filePath) {
return filePath != null && isDescendant(new File(filePath));
}
public String getRelativePath(File file) {
if (file == null)
return null;
String cleanPath = StringUtils.cleanPath(file.getAbsolutePath()).trim();
if (cleanPath.startsWith(this.rootDirectoryPath + "/")
&& cleanPath.length() > this.rootDirectoryPath.length() + 1) {
String relativePath = cleanPath.substring(this.rootDirectoryPath.length() + 1);
return relativePath.trim();
}
return null;
}
public String getRelativePath(String filePath) {
if (filePath == null)
return null;
return getRelativePath(new File(filePath));
}
}