/**
* This file is part of Waarp Project.
*
* Copyright 2009, Frederic Bregier, 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.common.file.passthrough;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
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.AbstractDir;
import org.waarp.common.file.FileInterface;
import org.waarp.common.file.OptsMLSxInterface;
import org.waarp.common.file.SessionInterface;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
/**
* Directory implementation for Passthrough Based. It is just an empty shell since in pass through
* mode, no directories or files really exist.
*
* If one wants to implement special actions, he/she just has to extend this class and override the
* default empty implementation.
*
* @author Frederic Bregier
*
*/
public abstract class PassthroughBasedDirImpl extends AbstractDir {
/**
* Factory for PassthroughFile
*/
protected static PassthroughFileFactory factory = null;
/**
* Passthrough object
*/
protected PassthroughFile pdir = null;
/**
* Internal Logger
*/
private static final WaarpLogger logger = WaarpLoggerFactory
.getLogger(PassthroughBasedDirImpl.class);
/**
* @param session
* @param optsMLSx
*/
public PassthroughBasedDirImpl(SessionInterface session,
OptsMLSxInterface optsMLSx) {
this.session = session;
this.optsMLSx = optsMLSx;
this.optsMLSx.setOptsModify((byte) -1);
this.optsMLSx.setOptsPerm((byte) -1);
this.optsMLSx.setOptsSize((byte) 1);
this.optsMLSx.setOptsType((byte) 1);
try {
pdir = factory.create(null, "/");
} catch (PassthroughException e) {
}
}
/**
* Finds all files matching a wildcard expression (based on '?', '~' or '*').
*
* @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 List<String> wildcardFiles(String pathWithWildcard)
throws CommandAbstractException {
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 after
// validating it
if (getSession().getAuth().isBusinessPathValid(pathWithWildcard)) {
resultPaths.add(pathWithWildcard);
}
return resultPaths;
}
// FIXME could support Wildcard path
PassthroughFile file;
try {
file = factory.create(null, pathWithWildcard);
} catch (PassthroughException e) {
throw new Reply553Exception("Error while creating a wildcard PassthroughFile: " +
e.getMessage());
}
try {
return file.wildcard(null);
} catch (PassthroughException e) {
throw new Reply553Exception("Error while getting a wildcard PassthroughFile: " +
e.getMessage());
}
}
/**
* Get the File from this path, checking first its validity
*
* @param path
* @return the FileInterface
* @throws CommandAbstractException
*/
protected File getFileFromPath(String path) throws CommandAbstractException {
String newdir = validatePath(path);
if (isAbsolute(newdir)) {
return new File(newdir);
}
String truedir = ((PassthroughBasedAuthImpl) getSession().getAuth())
.getAbsolutePath(newdir);
return new File(truedir);
}
/**
* Get the true file from the path
*
* @param path
* @return the true File from the path
* @throws CommandAbstractException
*/
protected File getTrueFile(String path) throws CommandAbstractException {
checkIdentify();
String newpath = consolidatePath(path);
List<String> paths = wildcardFiles(normalizePath(newpath));
if (paths.size() != 1) {
throw new Reply550Exception("File not found: " + paths.size() +
" founds");
}
String extDir = paths.get(0);
extDir = this.validatePath(extDir);
File file = getFileFromPath(extDir);
return file;
}
/**
* Get the relative path (without mount point)
*
* @param file
* @return the relative path
*/
protected String getRelativePath(File file) {
return ((PassthroughBasedAuthImpl) getSession().getAuth())
.getRelativePath(normalizePath(file.getAbsolutePath()));
}
public boolean changeDirectory(String path) throws CommandAbstractException {
checkIdentify();
String newpath = consolidatePath(path);
List<String> paths = wildcardFiles(newpath);
if (paths.size() != 1) {
logger.warn("CD error: {}", newpath);
throw new Reply550Exception("Directory not found: " + paths.size() +
" founds");
}
String extDir = paths.get(0);
extDir = this.validatePath(extDir);
if (isDirectory(extDir)) {
try {
pdir.changeDirectory(extDir);
} catch (PassthroughException e) {
throw new Reply550Exception("Directory not found");
}
currentDir = extDir;
return true;
}
throw new Reply550Exception("Directory not found");
}
public String mkdir(String directory) throws CommandAbstractException {
checkIdentify();
String newdirectory = consolidatePath(directory);
File dir = new File(newdirectory);
String parent = dir.getParentFile().getPath();
List<String> paths = wildcardFiles(normalizePath(parent));
if (paths.size() != 1) {
throw new Reply550Exception("Base Directory not found: " +
paths.size() + " founds");
}
String newDir = paths.get(0) + SEPARATOR + dir.getName();
newDir = this.validatePath(newDir);
PassthroughFile newdir;
try {
newdir = factory.create(null, newDir);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot create directory " + newDir);
}
try {
if (newdir.mkdir()) {
return newDir;
}
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot create directory " + newDir);
}
throw new Reply550Exception("Cannot create directory " + newDir);
}
public String rmdir(String directory) throws CommandAbstractException {
checkIdentify();
String newdirectory = consolidatePath(directory);
List<String> paths = wildcardFiles(normalizePath(newdirectory));
if (paths.size() != 1) {
throw new Reply550Exception("Directory not found: " + paths.size() +
" founds");
}
String extDir = paths.get(0);
extDir = this.validatePath(extDir);
PassthroughFile dir;
try {
dir = factory.create(null, extDir);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot delete directory " + extDir);
}
try {
if (dir.delete()) {
return extDir;
}
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot delete directory " + extDir);
}
throw new Reply550Exception("Cannot delete directory " + extDir);
}
public boolean isDirectory(String path) throws CommandAbstractException {
checkIdentify();
PassthroughFile dir;
try {
dir = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get isDirectory " + path);
}
return dir.isDirectory();
}
public boolean isFile(String path) throws CommandAbstractException {
checkIdentify();
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
return file.isFile();
}
public String getModificationTime(String path)
throws CommandAbstractException {
checkIdentify();
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.getModificationTime();
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get ModificationTime " + path);
}
}
public List<String> list(String path) throws CommandAbstractException {
checkIdentify();
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.list();
} catch (PassthroughException e) {
throw new Reply550Exception("List error " + e.getMessage());
}
}
public List<String> listFull(String path, boolean lsFormat)
throws CommandAbstractException {
checkIdentify();
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.listFull(lsFormat);
} catch (PassthroughException e) {
throw new Reply550Exception("List error " + e.getMessage());
}
}
public String fileFull(String path, boolean lsFormat)
throws CommandAbstractException {
checkIdentify();
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.fileFull(lsFormat);
} catch (PassthroughException e) {
throw new Reply550Exception("FileFull error " + e.getMessage());
}
}
/**
* Decide if Full time or partial time as in 'ls' command
*
* @return True if Full Time, False is Default (as in 'ls' command)
*/
protected boolean isFullTime() {
// FIXME should be it the default ?
return false;
}
public long getFreeSpace() throws CommandAbstractException {
checkIdentify();
try {
return pdir.getFreeSpace();
} catch (PassthroughException e) {
throw new Reply550Exception("FileFull error " + e.getMessage());
}
}
public FileInterface setUniqueFile()
throws CommandAbstractException {
checkIdentify();
// FIXME file: create a virtual unique file
String filename =
getFileFromPath(currentDir) + SEPARATOR +
getSession().getAuth().getUser() +
Long.toHexString(System.currentTimeMillis()) +
this.session.getUniqueExtension();
File file = new File(filename);
String currentFile = getRelativePath(file);
return newFile(normalizePath(currentFile), false);
}
public boolean canRead() throws CommandAbstractException {
checkIdentify();
return pdir.canRead();
}
public boolean canWrite() throws CommandAbstractException {
checkIdentify();
return pdir.canWrite();
}
public boolean exists() throws CommandAbstractException {
checkIdentify();
return pdir.exists();
}
public long getCRC(String path) throws CommandAbstractException {
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.getCRC();
} catch (PassthroughException e) {
throw new Reply550Exception("CRC error " + e.getMessage());
}
}
public byte[] getMD5(String path) throws CommandAbstractException {
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.getMD5();
} catch (PassthroughException e) {
throw new Reply550Exception("CRC error " + e.getMessage());
}
}
public byte[] getSHA1(String path) throws CommandAbstractException {
PassthroughFile file;
try {
file = factory.create(pdir, path);
} catch (PassthroughException e) {
throw new Reply550Exception("Cannot get File " + path);
}
try {
return file.getSHA1();
} catch (PassthroughException e) {
throw new Reply550Exception("CRC error " + e.getMessage());
}
}
}