R66Dir.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, 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.openr66.context.filesystem;
import org.waarp.common.command.exception.CommandAbstractException;
import org.waarp.common.command.exception.Reply550Exception;
import org.waarp.common.command.exception.Reply553Exception;
import org.waarp.common.file.filesystembased.FilesystemBasedDirImpl;
import org.waarp.common.file.filesystembased.FilesystemBasedOptsMLSxImpl;
import org.waarp.common.file.filesystembased.specific.FilesystemBasedCommonsIo;
import org.waarp.common.file.filesystembased.specific.FilesystemBasedDirJdkAbstract;
import org.waarp.openr66.context.R66Session;
import org.waarp.openr66.context.authentication.R66Auth;
import org.waarp.openr66.protocol.configuration.Configuration;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Directory representation
*/
public class R66Dir extends FilesystemBasedDirImpl {
/**
* @param session
*/
public R66Dir(final R66Session session) {
super(session, new FilesystemBasedOptsMLSxImpl());
}
@Override
public final R66File newFile(final String path, final boolean append)
throws CommandAbstractException {
return new R66File((R66Session) getSession(), this, path, append);
}
/**
* Same as setUnique() except that File will be prefixed by id and postfixed
* by filename
*
* @param prefix
* @param filename
*
* @return the R66File with a unique filename and a temporary extension
*
* @throws CommandAbstractException
*/
public synchronized R66File setUniqueFile(final long prefix,
final String filename)
throws CommandAbstractException {
checkIdentify();
final File file;
String prename = prefix + "_";
if (prename.length() < 3) {
prename = "xx_" + prename;
}
String basename = R66File.getBasename(filename);
if (basename.length() >
Configuration.configuration.getMaxfilenamelength() - 55) {
basename = basename.substring(basename.length() -
Configuration.configuration.getMaxfilenamelength() +
55);
}
try {
file =
File.createTempFile(prename, '_' + basename + Configuration.EXT_R66,
getFileFromPath(currentDir));
} catch (final IOException e) {
throw new Reply550Exception("Cannot create unique file from " + basename);
}
final String currentFile = getRelativePath(file);
return newFile(normalizePath(currentFile), false);
}
/**
* @param file
*
* @return the final unique basename without the temporary extension
*/
public static String getFinalUniqueFilename(final R66File file) {
String finalpath = file.getBasename();
final int pos = finalpath.lastIndexOf(Configuration.EXT_R66);
if (pos > 0) {
finalpath = finalpath.substring(0, pos);
}
return finalpath;
}
/**
* Finds all files matching a wildcard expression (based on '?', '~' or '*')
* but without checking
* BusinessPath, thus returning absolute path.
*
* @param pathWithWildcard The wildcard expression with a business
* path.
*
* @return List of String as relative paths matching the wildcard
* expression.
* Those files are tested as valid
* from business point of view. If Wildcard support is not active,
* if the
* path contains any wildcards,
* it will throw an error.
*
* @throws CommandAbstractException
*/
protected final List<String> wildcardFilesNoCheck(
final String pathWithWildcard) throws CommandAbstractException {
final List<String> resultPaths = new ArrayList<String>();
// First check if pathWithWildcard contains wildcards
if (!(pathWithWildcard.contains("*") || pathWithWildcard.contains("?") ||
pathWithWildcard.contains("~"))) {
// No so simply return the list containing this path
resultPaths.add(pathWithWildcard);
return resultPaths;
}
// Do we support Wildcard path
if (!FilesystemBasedDirJdkAbstract.ueApacheCommonsIo) {
throw new Reply553Exception("Wildcards in pathname is not allowed");
}
File wildcardFile = new File(pathWithWildcard);
final File rootFile;
if (ISUNIX) {
rootFile = new File("/");
} else {
rootFile = getCorrespondingRoot(wildcardFile);
}
// Split wildcard path into subdirectories.
final List<String> subdirs = new ArrayList<String>();
while (wildcardFile != null) {
final File parent = wildcardFile.getParentFile();
if (parent == null) {
subdirs.add(0, wildcardFile.getPath());
break;
}
subdirs.add(0, wildcardFile.getName());
if (parent.equals(rootFile)) {
// End of wildcard path
subdirs.add(0, parent.getPath());
break;
}
wildcardFile = parent;
}
List<File> basedPaths = new ArrayList<File>();
// First set root
basedPaths.add(new File(subdirs.get(0)));
int i = 1;
// For each wilcard subdirectory
while (i < subdirs.size()) {
// Set current filter
final FileFilter fileFilter =
FilesystemBasedCommonsIo.getWildcardFileFilter(subdirs.get(i));
final List<File> newBasedPaths = new ArrayList<File>();
// Look for matches in all the current search paths
for (final File dir : basedPaths) {
if (dir.isDirectory()) {
Collections.addAll(newBasedPaths, dir.listFiles(fileFilter));
}
}
// base Search Path changes now
basedPaths = newBasedPaths;
i++;
}
// Valid each file first
for (final File file : basedPaths) {
resultPaths.add(file.getAbsolutePath());
}
return resultPaths;
}
/**
* Create a new file according to the path without checking BusinessPath, so
* as external File.
*
* @param path
*
* @return the File created
*
* @throws CommandAbstractException
*/
public final R66File setFileNoCheck(final String path)
throws CommandAbstractException {
checkIdentify();
final String newpath = consolidatePath(path);
final List<String> paths = wildcardFilesNoCheck(newpath);
if (paths.size() != 1) {
throw new Reply550Exception(
"File not found from: " + newpath + " and " + paths.size() +
" founds");
}
final String extDir = paths.get(0);
return new R66File((R66Session) getSession(), this, extDir);
}
/**
* This method returns the Full path for the current directory
*
* @return the full path associated with the current Dir
*/
public final String getFullPath() {
if (session.getAuth() == null) {
return currentDir;
}
if (isAbsolute(currentDir)) {
return currentDir;
}
return ((R66Auth) session.getAuth()).getAbsolutePath(currentDir);
}
@Override
public String toString() {
return "Dir: " + currentDir;
}
}