You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2019/02/19 14:46:00 UTC

[mina-sshd] 02/02: [SSHD-897] Moved some shell stream related classes to sshd-common

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch SSHD-897
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit b47195e4f156e475639de2fe3ceae232376b0d1d
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Tue Feb 19 16:45:47 2019 +0200

    [SSHD-897] Moved some shell stream related classes to sshd-common
---
 .../org/apache/sshd/common/channel/PtyMode.java    | 108 ++++++++++++++++++++-
 .../sshd/server/shell/TtyFilterInputStream.java    |   3 +-
 .../sshd/server/shell/TtyFilterOutputStream.java   |   0
 .../apache/sshd/common/channel/PtyModeTest.java    |   8 +-
 .../sshd/common/channel/PtyModeValueTest.java      |  97 ++++++++++++++++++
 .../AuthorizedKeyEntryLoginOptionsParseTest.java   |   6 +-
 .../server/shell/TtyFilterInputStreamTest.java     |   4 +-
 .../server/shell/TtyFilterOutputStreamTest.java    |   8 +-
 .../sshd/common/util/io/LineOutputStreamTest.java  |   3 +
 9 files changed, 222 insertions(+), 15 deletions(-)

diff --git a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java
index 21af35e..a4745e5 100644
--- a/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java
+++ b/sshd-common/src/main/java/org/apache/sshd/common/channel/PtyMode.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.NavigableMap;
 import java.util.Set;
 import java.util.function.Function;
+import java.util.function.ToIntFunction;
 
 import org.apache.sshd.common.util.GenericUtils;
 
@@ -295,10 +296,29 @@ public enum PtyMode {
     public static final Set<PtyMode> MODES =
         Collections.unmodifiableSet(EnumSet.allOf(PtyMode.class));
 
-    private static final NavigableMap<Integer, PtyMode> COMMANDS =
+    public static final NavigableMap<Integer, PtyMode> COMMANDS =
         Collections.unmodifiableNavigableMap(
             GenericUtils.toSortedMap(MODES, PtyMode::toInt, Function.identity(), Comparator.naturalOrder()));
 
+    /**
+     * A {@code null}-safe {@link ToIntFunction} that returns the {@link PtyMode#toInt()} value and (-1) for {@code null}
+     */
+    public static final ToIntFunction<PtyMode> OPCODE_EXTRACTOR = v -> (v == null) ? -1 : v.toInt();
+
+    /**
+     * A {@code null}-safe {@link Comparator} of {@link PtyMode} values
+     * according to their {@link PtyMode#toInt()} value
+     * @see #OPCODE_EXTRACTOR
+     */
+    public static final Comparator<PtyMode> BY_OPCODE = new Comparator<PtyMode>() {
+            @Override
+            public int compare(PtyMode o1, PtyMode o2) {
+                int v1 = OPCODE_EXTRACTOR.applyAsInt(o1);
+                int v2 = OPCODE_EXTRACTOR.applyAsInt(o2);
+                return Integer.compare(v1, v2);
+            }
+        };
+
     private final int v;
 
     PtyMode(int v) {
@@ -318,6 +338,20 @@ public enum PtyMode {
         return COMMANDS.get(0x00FF & b);
     }
 
+    public static PtyMode fromName(String name) {
+        if (GenericUtils.isEmpty(name)) {
+            return null;
+        }
+
+        for (PtyMode m : MODES) {
+            if (name.equalsIgnoreCase(m.name())) {
+                return m;
+            }
+        }
+
+        return null;
+    }
+
     /**
      * @param options The options to enable - ignored if {@code null}/empty
      * @return A {@link Map} where all the specified {@link PtyMode}s have {@link #TRUE_SETTING}
@@ -391,6 +425,63 @@ public enum PtyMode {
     }
 
     /**
+     * @param modes The {@link Map} of {@link PtyMode}s resolved by the &quot;pty-req&quot; message.
+     * @param enablers A {@link Collection} of enabler settings to be consulted
+     * @param defaultValue The default value to be used if no definite setting could be deduced
+     * @return {@code true} if the CR mode is enabled:</BR>
+     * <UL>
+     *      <LI>
+     *      If<tt>modes</tt> or <tt>enablers</tt> are {@code null}/empty
+     *      then <tt>defaultValue</tt> is used
+     *      </LI>
+     *
+     *      <LI>
+     *      If <U>any</U> of the <tt>enablers</tt> modes are enabled
+     *      then the CR mode is enabled.
+     *      </LI>
+     *
+     *      <LI>
+     *      If <U>none</U> of the <tt>enablers</tt> modes were specified
+     *      then use  <tt>defaultValue</tt>
+     *      </LI>
+     *
+     *      <LI>
+     *      Otherwise (i.e., at least one or more of the <tt>enablers</tt>
+     *      modes were specified, but <U>all</U> of them said {@code no})
+     *      then {@code false}.
+     *      </LI>
+     * </UL>
+     */
+    public static boolean getBooleanSettingValue(
+            Map<PtyMode, ?> modes, Collection<PtyMode> enablers, boolean defaultValue) {
+        if (GenericUtils.isEmpty(modes) || GenericUtils.isEmpty(enablers)) {
+            return defaultValue;
+        }
+
+        int settingsCount = 0;
+        for (PtyMode m : enablers) {
+            Object v = modes.get(m);
+            if (v == null) {
+                continue;
+            }
+
+            settingsCount++;
+
+            // if any setting says yes then use it
+            if (getBooleanSettingValue(v)) {
+                return true;
+            }
+        }
+
+        // ALL (!) settings have said NO
+        if (settingsCount > 0) {
+            return false;
+        } else {
+            return defaultValue;    // none of the settings has been found - assume default
+        }
+    }
+
+    /**
      * @param v The value to be tested
      * @return {@code true} if <U>all</U> of these conditions hold:</BR>
      * <UL>
@@ -410,4 +501,19 @@ public enum PtyMode {
     public static boolean getBooleanSettingValue(int v) {
         return v != 0;
     }
+
+    /**
+     * @param m The {@link PtyMode}
+     * @return {@code true} if not {@code null} and one of the settings that
+     * refers to a character value - name usually starts with {@code Vxxx}
+     */
+    public static boolean isCharSetting(PtyMode m) {
+        if (m == null) {
+            return false;
+        }
+
+        String name = m.name();
+        char ch = name.charAt(0);
+        return (ch == 'v') || (ch == 'V');
+    }
 }
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java
similarity index 98%
rename from sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java
rename to sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java
index b894805..5760310 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterInputStream.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import org.apache.sshd.common.channel.PtyMode;
@@ -51,7 +52,7 @@ public class TtyFilterInputStream extends FilterInputStream {
     }
 
     public TtyFilterInputStream(InputStream in, Collection<PtyMode> ttyOptions) {
-        super(in);
+        super(Objects.requireNonNull(in, "No input stream provided"));
         // we create a copy of the options so as to avoid concurrent modifications
         this.ttyOptions = GenericUtils.of(ttyOptions);  // TODO validate non-conflicting options
     }
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java b/sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java
similarity index 100%
rename from sshd-core/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java
rename to sshd-common/src/main/java/org/apache/sshd/server/shell/TtyFilterOutputStream.java
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java
index 3234948..69ae5e8 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeTest.java
@@ -42,12 +42,8 @@ public class PtyModeTest extends JUnitTestSupport {
     }
 
     @Test
-    public void testFromInt() {
-        for (PtyMode expected : PtyMode.MODES) {
-            int num = expected.toInt();
-            PtyMode actual = PtyMode.fromInt(num);
-            assertSame("Mismatched result for value=" + num, expected, actual);
-        }
+    public void testOpcodeExtractorOnNull() {
+        assertEquals(-1, PtyMode.OPCODE_EXTRACTOR.applyAsInt(null));
     }
 
     @Test
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java
new file mode 100644
index 0000000..98ab7ce
--- /dev/null
+++ b/sshd-common/src/test/java/org/apache/sshd/common/channel/PtyModeValueTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.common.channel;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+/**
+ * TODO Add javadoc
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
+@UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
+public class PtyModeValueTest extends JUnitTestSupport {
+    private final PtyMode expected;
+
+    public PtyModeValueTest(PtyMode expected) {
+        this.expected = expected;
+    }
+
+    @Parameters(name = "{0}")
+    public static List<Object[]> parameters() {
+        return parameterize(PtyMode.MODES);
+    }
+
+    @Test
+    public void testOpcodeExtractor() {
+        assertEquals(expected.toInt(), PtyMode.OPCODE_EXTRACTOR.applyAsInt(expected));
+    }
+
+    @Test
+    public void testByOpcodeComparator() {
+        int v1 = expected.toInt();
+        for (PtyMode actual : PtyMode.MODES) {
+            int v2 = actual.toInt();
+            int cmpExpected = Integer.signum(Integer.compare(v1, v2));
+            int cmpActual = Integer.signum(PtyMode.BY_OPCODE.compare(expected, actual));
+            assertEquals(expected + " vs. " + actual, cmpExpected, cmpActual);
+        }
+    }
+
+    @Test
+    public void testFromName() {
+        String name = expected.name();
+        for (int index = 0; index < Byte.SIZE; index++) {
+            PtyMode actual = PtyMode.fromName(name);
+            assertSame(name, expected, actual);
+            name = shuffleCase(name);
+        }
+    }
+
+    @Test
+    public void testGetBooleanSettingValueOnNullOrEmptyValues() {
+        for (@SuppressWarnings("unchecked") Map<PtyMode, ?> modes : new Map[] {null, Collections.emptyMap()}) {
+            String s = (modes == null) ? "null" : "empty";
+            assertFalse("Map is " + s, PtyMode.getBooleanSettingValue(modes, expected));
+        }
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "[" + expected + "]";
+    }
+}
diff --git a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java
index d912998..c37aa28 100644
--- a/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/common/config/keys/AuthorizedKeyEntryLoginOptionsParseTest.java
@@ -26,8 +26,10 @@ import java.util.Map;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
 import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.junit.runners.Parameterized;
@@ -40,13 +42,15 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
 @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
 public class AuthorizedKeyEntryLoginOptionsParseTest extends JUnitTestSupport {
     private final String value;
     private final String loginPart;
     private final String keyPart;
     private final Map<String, String> options;
 
-    public AuthorizedKeyEntryLoginOptionsParseTest(String value, String loginPart, String keyPart, Map<String, String> options) {
+    public AuthorizedKeyEntryLoginOptionsParseTest(
+            String value, String loginPart, String keyPart, Map<String, String> options) {
         this.value = value;
         this.loginPart = loginPart;
         this.keyPart = keyPart;
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java
similarity index 98%
rename from sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java
rename to sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java
index bd4913a..a17fa01 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterInputStreamTest.java
@@ -40,8 +40,8 @@ import org.apache.sshd.common.channel.PtyMode;
 import org.apache.sshd.common.util.GenericUtils;
 import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
 import org.apache.sshd.common.util.io.IoUtils;
-import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
 import org.apache.sshd.util.test.NoIoTestCase;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -59,7 +59,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 @RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
 @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
 @Category({ NoIoTestCase.class })
-public class TtyFilterInputStreamTest extends BaseTestSupport {
+public class TtyFilterInputStreamTest extends JUnitTestSupport {
     private static final List<PtyMode> MODES =
         Collections.unmodifiableList(
             Stream.concat(Stream.of(PtyMode.ECHO), TtyFilterInputStream.INPUT_OPTIONS.stream())
diff --git a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java
similarity index 95%
rename from sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java
rename to sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java
index 5844836..be72b32 100644
--- a/sshd-core/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java
+++ b/sshd-common/src/test/java/org/apache/sshd/server/shell/TtyFilterOutputStreamTest.java
@@ -34,8 +34,8 @@ import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.apache.sshd.common.channel.PtyMode;
-import org.apache.sshd.util.test.BaseTestSupport;
 import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
+import org.apache.sshd.util.test.JUnitTestSupport;
 import org.apache.sshd.util.test.NoIoTestCase;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
@@ -53,7 +53,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 @RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
 @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
 @Category({ NoIoTestCase.class })
-public class TtyFilterOutputStreamTest extends BaseTestSupport {
+public class TtyFilterOutputStreamTest extends JUnitTestSupport {
     private final PtyMode mode;
 
     public TtyFilterOutputStreamTest(PtyMode mode) {
@@ -71,8 +71,8 @@ public class TtyFilterOutputStreamTest extends BaseTestSupport {
                 getClass().getSimpleName(), getCurrentTestName(),
                 "(" + mode + ")", new Date(System.currentTimeMillis()).toString());
 
-        final AtomicInteger crCount = new AtomicInteger(0);
-        final AtomicInteger lfCount = new AtomicInteger(0);
+        AtomicInteger crCount = new AtomicInteger(0);
+        AtomicInteger lfCount = new AtomicInteger(0);
         try (OutputStream output = new OutputStream() {
                 @Override
                 public void write(int b) throws IOException {
diff --git a/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java b/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java
index c49f608..8a449ec 100644
--- a/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java
+++ b/sshd-contrib/src/test/java/org/apache/sshd/common/util/io/LineOutputStreamTest.java
@@ -32,8 +32,10 @@ import java.util.List;
 
 import org.apache.sshd.util.test.JUnit4ClassRunnerWithParametersFactory;
 import org.apache.sshd.util.test.JUnitTestSupport;
+import org.apache.sshd.util.test.NoIoTestCase;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
+import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
 import org.junit.runners.Parameterized;
@@ -46,6 +48,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory;
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @RunWith(Parameterized.class)   // see https://github.com/junit-team/junit/wiki/Parameterized-tests
 @UseParametersRunnerFactory(JUnit4ClassRunnerWithParametersFactory.class)
+@Category({ NoIoTestCase.class })
 public class LineOutputStreamTest extends JUnitTestSupport {
     private final boolean withCR;