/*
* Copyright (c) 2008-2014, XebiaLabs B.V., All rights reserved.
*
*
* Overthere is licensed under the terms of the GPLv2
* <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most XebiaLabs Libraries.
* There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
* this software, see the FLOSS License Exception
* <http://github.com/xebialabs/overthere/blob/master/LICENSE>.
*
* This program 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; version 2
* of the License.
*
* This program 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 this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
package com.xebialabs.overthere.ssh;
import com.xebialabs.overthere.*;
import com.xebialabs.overthere.spi.BaseOverthereFile;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import static com.xebialabs.overthere.OperatingSystemFamily.WINDOWS;
import static com.xebialabs.overthere.util.OverthereUtils.mkString;
/**
* A file on a host connected through SSH.
*/
abstract class SshFile<C extends SshConnection> extends BaseOverthereFile<C> {
protected List<String> pathComponents;
/**
* Constructs an SshOverthereFile
*
* @param connection the connection to the host
* @param path the path of the file on the host
*/
SshFile(C connection, String path) {
this(connection, splitPath(path, connection.getHostOperatingSystem()));
}
SshFile(C connection, List<String> pathComponents) {
super(connection);
checkWindowsPath(pathComponents, connection.getHostOperatingSystem());
this.pathComponents = pathComponents;
}
@Override
public String getPath() {
return joinPath(pathComponents, connection.getHostOperatingSystem());
}
@Override
public boolean isHidden() {
return getName().startsWith(".");
}
@Override
public String getName() {
if (pathComponents.isEmpty()) {
return connection.getHostOperatingSystem().getFileSeparator();
} else {
return pathComponents.get(pathComponents.size() - 1);
}
}
@Override
public OverthereFile getParentFile() {
if (pathComponents.isEmpty()) {
// The root path is its own parent.
return this;
}
if (connection.getHostOperatingSystem() == WINDOWS && pathComponents.size() == 1) {
// On Windows, the drive path is its own parent
return this;
}
return connection.getFile(joinPath(pathComponents.subList(0, pathComponents.size() - 1), connection.getHostOperatingSystem()));
}
@Override
public void delete() throws RuntimeIOException {
if (exists()) {
if (isDirectory()) {
deleteDirectory();
} else {
deleteFile();
}
}
}
protected abstract void deleteFile();
protected abstract void deleteDirectory();
protected int executeCommand(OverthereExecutionOutputHandler outHandler, OverthereExecutionOutputHandler errHandler, CmdLine commandLine) {
return connection.execute(outHandler, errHandler, commandLine);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof SshFile)) {
return false;
}
return getPath().equals(((SshFile<?>) obj).getPath());
}
@Override
public int hashCode() {
return getPath().hashCode();
}
@Override
public String toString() {
String p = getPath();
if (p.length() >= 1 && p.charAt(0) == '/') {
return getConnection() + p;
} else {
return getConnection() + "/" + p;
}
}
static List<String> splitPath(String path, OperatingSystemFamily os) {
Pattern s = os == WINDOWS ? WINDOWS_PATH_SPLITTER : UNIX_PATH_SPLITTER;
List<String> l = new ArrayList<String>();
for (String p : s.split(path)) {
if (p.isEmpty()) continue;
l.add(p);
}
return l;
}
static String joinPath(List<String> pathComponents, OperatingSystemFamily os) {
String fileSep = os.getFileSeparator();
if (pathComponents.isEmpty()) {
return fileSep;
}
if (os == WINDOWS) {
String path = mkString(pathComponents, fileSep);
if (pathComponents.size() == 1) {
path += fileSep;
}
return path;
} else {
return fileSep + mkString(pathComponents, fileSep);
}
}
static void checkWindowsPath(List<String> pathComponents, OperatingSystemFamily os) {
if (os == WINDOWS && pathComponents.isEmpty()) {
throw new IllegalArgumentException("Empty path is not allowed on Windows");
}
}
private static final Pattern UNIX_PATH_SPLITTER = Pattern.compile("/");
private static final Pattern WINDOWS_PATH_SPLITTER = Pattern.compile("[/\\\\]");
}