org.apache.sshd.cli.client.ScpCommandMain Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.cli.client;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.attribute.PosixFilePermission;
import java.security.KeyPair;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.apache.sshd.cli.CliLogger;
import org.apache.sshd.client.ClientFactoryManager;
import org.apache.sshd.client.auth.AuthenticationIdentitiesProvider;
import org.apache.sshd.client.config.hosts.HostConfigEntry;
import org.apache.sshd.client.session.ClientSession;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.ReflectionUtils;
import org.apache.sshd.common.util.io.input.NoCloseInputStream;
import org.apache.sshd.common.util.threads.ThreadUtils;
import org.apache.sshd.scp.client.ScpClient;
import org.apache.sshd.scp.client.ScpClient.Option;
import org.apache.sshd.scp.client.ScpClientCreator;
import org.apache.sshd.scp.client.ScpRemote2RemoteTransferHelper;
import org.apache.sshd.scp.client.ScpRemote2RemoteTransferListener;
import org.apache.sshd.scp.common.ScpLocation;
import org.apache.sshd.scp.common.ScpTransferEventListener;
import org.apache.sshd.scp.common.helpers.ScpAckInfo;
import org.apache.sshd.scp.common.helpers.ScpReceiveDirCommandDetails;
import org.apache.sshd.scp.common.helpers.ScpReceiveFileCommandDetails;
import org.apache.sshd.scp.common.helpers.ScpTimestampCommandDetails;
import org.slf4j.Logger;
/**
* @see SCP(1) - manual page
* @author Apache MINA SSHD Project
*/
public class ScpCommandMain extends SshClientCliSupport {
/**
* Command line option used to indicate a non-default port
*/
public static final String SCP_PORT_OPTION = "-P";
/**
* Copies between two remote hosts are transferred through the local host
*/
public static final String SCP_REMOTE_TO_REMOTE_OPTION = "-3";
public ScpCommandMain() {
super(); // in case someone wants to extend it
}
/* -------------------------------------------------------------------------------- */
public static String[] normalizeCommandArguments(PrintStream stdout, PrintStream stderr, String... args) {
int numArgs = GenericUtils.length(args);
if (numArgs <= 0) {
return args;
}
List effective = new ArrayList<>(numArgs);
boolean error = false;
boolean threeWay = false;
for (int index = 0; (index < numArgs) && (!error); index++) {
String argName = args[index];
// handled by 'setupClientSession'
if (isArgumentedOption(SCP_PORT_OPTION, argName) || "-creator".equals(argName)) {
index++;
if (index >= numArgs) {
error = CliLogger.showError(stderr, "option requires an argument: " + argName);
break;
}
effective.add(argName);
effective.add(args[index]);
} else if ("-r".equals(argName) || "-p".equals(argName)
|| "-q".equals(argName) || "-C".equals(argName)
|| "-v".equals(argName) || "-vv".equals(argName) || "-vvv".equals(argName)) {
effective.add(argName);
} else if (SCP_REMOTE_TO_REMOTE_OPTION.equals(argName)) {
threeWay = true;
effective.add(argName);
} else if (argName.charAt(0) == '-') {
error = CliLogger.showError(stderr, "Unknown option: " + argName);
break;
} else {
index++;
if (index >= numArgs) {
error = CliLogger.showError(stderr, "Not enough arguments");
break;
}
ScpLocation source = new ScpLocation(argName);
ScpLocation target = new ScpLocation(args[index]);
if (index < (numArgs - 1)) {
error = CliLogger.showError(stderr, "Unexpected extra arguments");
break;
}
if (threeWay) {
if (source.isLocal() || target.isLocal()) {
error = CliLogger.showError(stderr, "Both targets must be remote for the 3-way copy option");
break;
}
adjustRemoteTargetArguments(source, source, target, effective);
} else {
if (source.isLocal() == target.isLocal()) {
error = CliLogger.showError(stderr, "Both targets are either remote or local");
break;
}
ScpLocation remote = source.isLocal() ? target : source;
adjustRemoteTargetArguments(remote, source, target, effective);
}
break;
}
}
if (error) {
return null;
}
return effective.toArray(new String[effective.size()]);
}
/* -------------------------------------------------------------------------------- */
private static void adjustRemoteTargetArguments(
ScpLocation remote, ScpLocation source, ScpLocation target, Collection effective) {
int port = remote.resolvePort();
if (port != SshConstants.DEFAULT_PORT) {
effective.add(SCP_PORT_OPTION);
effective.add(Integer.toString(port));
}
effective.add(remote.resolveUsername() + "@" + remote.getHost());
effective.add(source.toString());
effective.add(target.toString());
}
/* -------------------------------------------------------------------------------- */
public static ScpClientCreator resolveScpClientCreator(PrintStream stderr, String... args) {
String className = null;
for (int index = 0, numArgs = GenericUtils.length(args); index < numArgs; index++) {
String argName = args[index];
if ("-creator".equals(argName)) {
index++;
if (index >= numArgs) {
CliLogger.showError(stderr, "option requires an argument: " + argName);
return null;
}
className = args[index];
}
}
if (GenericUtils.isEmpty(className)) {
className = System.getProperty(ScpClientCreator.class.getName());
}
if (GenericUtils.isEmpty(className)) {
return ScpClientCreator.instance();
}
try {
ClassLoader cl = ThreadUtils.resolveDefaultClassLoader(ScpClientCreator.class);
Class> clazz = cl.loadClass(className);
return ReflectionUtils.newInstance(clazz, ScpClientCreator.class);
} catch (Exception e) {
stderr.append("WARNING: Failed (").append(e.getClass().getSimpleName()).append(')')
.append(" to instantiate ").append(className)
.append(": ").println(e.getMessage());
stderr.flush();
return null;
}
}
/* -------------------------------------------------------------------------------- */
public static Set
© 2015 - 2024 Weber Informatics LLC | Privacy Policy