All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sshd.cli.client.ScpCommandMain Maven / Gradle / Ivy

There is a newer version: 2.14.0
Show newest version
/*
 * 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