/* * 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.client.subsystem.sftp; import java.util.Collection; import java.util.List; import java.util.stream.StreamSupport; import org.apache.sshd.client.session.ClientSession; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.NumberUtils; import org.apache.sshd.common.util.ValidateUtils; /** * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a> */ @FunctionalInterface public interface SftpVersionSelector { /** * An {@link SftpVersionSelector} that returns the current version */ SftpVersionSelector CURRENT = new NamedVersionSelector("CURRENT", (session, current, available) -> current); /** * An {@link SftpVersionSelector} that returns the maximum available version */ SftpVersionSelector MAXIMUM = new NamedVersionSelector("MAXIMUM", (session, current, available) -> GenericUtils.stream(available).mapToInt(Integer::intValue).max().orElse(current)); /** * An {@link SftpVersionSelector} that returns the maximum available version */ SftpVersionSelector MINIMUM = new NamedVersionSelector("MINIMUM", (session, current, available) -> GenericUtils.stream(available).mapToInt(Integer::intValue).min().orElse(current)); /** * @param session The {@link ClientSession} through which the SFTP connection is made * @param current The current version negotiated with the server * @param available Extra versions available - may be empty and/or contain * only the current one * @return The new requested version - if same as current, then nothing is done */ int selectVersion(ClientSession session, int current, List<Integer> available); /** * Creates a selector the always returns the requested (fixed version) regardless * of what the current or reported available versions are. If the requested version * is not reported as available then an exception will be eventually thrown by the * client during re-negotiation phase. * * @param version The requested version * @return The {@link SftpVersionSelector} */ static SftpVersionSelector fixedVersionSelector(final int version) { return (session, current, available) -> version; } /** * Selects a version in order of preference - if none of the preferred * versions is listed as available then an exception is thrown when the * {@link SftpVersionSelector#selectVersion(ClientSession, int, List)} method is invoked * * @param preferred The preferred versions in decreasing order of * preference (i.e., most preferred is 1st) - may not be {@code null}/empty * @return A {@link SftpVersionSelector} that attempts to select * the most preferred version that is also listed as available. */ static SftpVersionSelector preferredVersionSelector(final int... preferred) { return preferredVersionSelector(NumberUtils.asList(preferred)); } /** * Selects a version in order of preference - if none of the preferred * versions is listed as available then an exception is thrown when the * {@link SftpVersionSelector#selectVersion(ClientSession, int, List)} method is invoked * * @param preferred The preferred versions in decreasing order of * preference (i.e., most preferred is 1st) * @return A {@link SftpVersionSelector} that attempts to select * the most preferred version that is also listed as available. */ static SftpVersionSelector preferredVersionSelector(final Iterable<? extends Number> preferred) { ValidateUtils.checkNotNullAndNotEmpty((Collection<?>) preferred, "Empty preferred versions"); return (session, current, available) -> StreamSupport.stream(preferred.spliterator(), false) .mapToInt(Number::intValue) .filter(v -> v == current || available.contains(v)) .findFirst() .orElseThrow(() -> new IllegalStateException("Preferred versions (" + preferred + ") not available: " + available)); } class NamedVersionSelector implements SftpVersionSelector { private final String name; private final SftpVersionSelector selector; public NamedVersionSelector(String name, SftpVersionSelector selector) { this.name = name; this.selector = selector; } @Override public int selectVersion(ClientSession session, int current, List<Integer> available) { return selector.selectVersion(session, current, available); } @Override public String toString() { return name; } } }