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 2015/11/17 08:10:54 UTC

[2/6] mina-sshd git commit: Moved StandardEnvironment to its own file

Moved StandardEnvironment to its own file


Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/512cbd99
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/512cbd99
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/512cbd99

Branch: refs/heads/master
Commit: 512cbd99b684008e28769bd445601f4ffcbbd772
Parents: 77e1123
Author: Lyor Goldstein <lg...@vmware.com>
Authored: Tue Nov 17 09:07:02 2015 +0200
Committer: Lyor Goldstein <lg...@vmware.com>
Committed: Tue Nov 17 09:07:02 2015 +0200

----------------------------------------------------------------------
 .../org/apache/sshd/server/Environment.java     |  33 ++--
 .../java/org/apache/sshd/server/Signal.java     |  66 ++++++--
 .../apache/sshd/server/StandardEnvironment.java | 157 +++++++++++++++++++
 3 files changed, 230 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/512cbd99/sshd-core/src/main/java/org/apache/sshd/server/Environment.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/Environment.java b/sshd-core/src/main/java/org/apache/sshd/server/Environment.java
index 6449f34..192cb86 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/Environment.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/Environment.java
@@ -34,18 +34,21 @@ public interface Environment {
      * Key for the user environment variable
      */
     String ENV_USER = "USER";
+
     /**
      * Key for the lines environment variable. Specifies the number of
-     * lines visible on the client side. {@link Environment#ENV_LINES} and
-     * {@link Environment#ENV_COLUMNS} make up the console screen size.
+     * lines visible on the client side. {@link #ENV_LINES} and
+     * {@link #ENV_COLUMNS} make up the console screen size.
      */
     String ENV_LINES = "LINES";
+
     /**
      * Key for the columns environment variable. Specifies the number of
-     * columns visible on the client side. {@link Environment#ENV_LINES} and
-     * {@link Environment#ENV_COLUMNS} make up the console screen size.
+     * columns visible on the client side. {@link #ENV_LINES} and
+     * {@link #ENV_COLUMNS} make up the console screen size.
      */
     String ENV_COLUMNS = "COLUMNS";
+
     /**
      * Key for the term environment variable. Describes the terminal or
      * terminal emulation which is in use.
@@ -55,44 +58,44 @@ public interface Environment {
     /**
      * Retrieve the environment map
      *
-     * @return the environment map
+     * @return the environment {@link Map} - never {@code null}
      */
     Map<String, String> getEnv();
 
     /**
-     * Retrieve the pty modes
+     * Retrieve the PTY modes settings
      *
-     * @return the map of pty modes
+     * @return the {@link Map} of {@link PtyMode}s - never {@code null}
      */
     Map<PtyMode, Integer> getPtyModes();
 
     /**
-     * Add a qualified listener for the specific signal
+     * Add a qualified listener for the specific signals
      *
-     * @param listener the listener to register
-     * @param signal   the signal the listener is interested in
+     * @param listener the {@link SignalListener} to register
+     * @param signal   the {@link Signal}s  the listener is interested in
      */
     void addSignalListener(SignalListener listener, Signal... signal);
 
     /**
-     * Add a qualified listener for the specific set of signal
+     * Add a qualified listener for the specific signals
      *
-     * @param listener the listener to register
-     * @param signals  the signals the listener is interested in
+     * @param listener the {@link SignalListener} to register
+     * @param signals  the {@link Signal}s the listener is interested in
      */
     void addSignalListener(SignalListener listener, Collection<Signal> signals);
 
     /**
      * Add a global listener for all signals
      *
-     * @param listener the listener to register
+     * @param listener the {@link SignalListener} to register
      */
     void addSignalListener(SignalListener listener);
 
     /**
      * Remove a previously registered listener for all the signals it was registered
      *
-     * @param listener the listener to remove
+     * @param listener the {@link SignalListener} to remove
      */
     void removeSignalListener(SignalListener listener);
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/512cbd99/sshd-core/src/main/java/org/apache/sshd/server/Signal.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/Signal.java b/sshd-core/src/main/java/org/apache/sshd/server/Signal.java
index 3cb3efb..3d88580 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/Signal.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/Signal.java
@@ -23,6 +23,9 @@ import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.sshd.common.util.GenericUtils;
 
 /**
  * System signals definition that the shell can receive.
@@ -63,11 +66,40 @@ public enum Signal {
     PWR(30);
 
     /**
-     * A {@link Set} of all the available {@link Signal}s
+     * An un-modifiable {@link Set} of all the available {@link Signal}s
      */
     public static final Set<Signal> SIGNALS = Collections.unmodifiableSet(EnumSet.allOf(Signal.class));
 
-    private static final Map<String, Signal> LOOKUP_TABLE = new HashMap<String, Signal>(40);
+    /**
+     * An un-modifiable <U>case-insensitive</U> {@link Map} of the names of all available {@link Signal}s
+     * @see #SIGNALS
+     */
+    public static final Map<String, Signal> NAME_LOOKUP_TABLE =
+            Collections.unmodifiableMap(new TreeMap<String, Signal>(String.CASE_INSENSITIVE_ORDER) {
+                private static final long serialVersionUID = 1L;    // we're not serializing it
+
+                {
+                    for (Signal s : SIGNALS) {
+                        put(s.name(), s);
+                    }
+                }
+            });
+
+    /**
+     * An un-modifiable {@link Map} of the numeric values of all available {@link Signal}s
+     * @see #SIGNALS
+     * @see #getNumeric()
+     */
+    public static final Map<Integer, Signal> NUMERIC_LOOKUP_TABLE =
+            Collections.unmodifiableMap(new HashMap<Integer, Signal>(SIGNALS.size()) {
+                private static final long serialVersionUID = 1L;    // we're not serializing it
+
+                {
+                    for (Signal s : SIGNALS) {
+                        put(Integer.valueOf(s.getNumeric()), s);
+                    }
+                }
+            });
 
     private final int numeric;
 
@@ -75,19 +107,31 @@ public enum Signal {
         this.numeric = numeric;
     }
 
-    static {
-        // registering the signals in the lookup table to allow faster
-        // string based signal lookups
-        for (Signal s : Signal.values()) {
-            LOOKUP_TABLE.put(s.name(), s);
-        }
+    /**
+     * @return The signal's numeric value
+     */
+    public int getNumeric() {
+        return numeric;
     }
 
+    /**
+     * Retrieves a signal value given its name
+     *
+     * @param name The signal's name (case <U>insensitive</U>) - ignored if {@code null}/empty
+     * @return The matching {@link Signal} or {@code null} if no match found
+     */
     public static Signal get(String name) {
-        return LOOKUP_TABLE.get(name);
+        return GenericUtils.isEmpty(name) ? null : NAME_LOOKUP_TABLE.get(name);
     }
 
-    public int getNumeric() {
-        return numeric;
+    /**
+     * Retrieves a signal value given its numeric value
+     *
+     * @param num The signal's numeric value
+     * @return The matching {@link Signal} or {@code null} if no match found
+     * @see #getNumeric()
+     */
+    public static Signal get(int num) {
+        return NUMERIC_LOOKUP_TABLE.get(Integer.valueOf(num));
     }
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/512cbd99/sshd-core/src/main/java/org/apache/sshd/server/StandardEnvironment.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/StandardEnvironment.java b/sshd-core/src/main/java/org/apache/sshd/server/StandardEnvironment.java
new file mode 100644
index 0000000..011b52a
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/StandardEnvironment.java
@@ -0,0 +1,157 @@
+/*
+ * 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.server;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.sshd.common.channel.PtyMode;
+import org.apache.sshd.common.util.GenericUtils;
+import org.apache.sshd.common.util.ValidateUtils;
+import org.apache.sshd.common.util.logging.AbstractLoggingBean;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class StandardEnvironment extends AbstractLoggingBean implements Environment {
+    private final Map<Signal, Set<SignalListener>> listeners;
+    private final Map<String, String> env;
+    private final Map<PtyMode, Integer> ptyModes;
+
+    public StandardEnvironment() {
+        listeners = new ConcurrentHashMap<>(3);
+        env = new ConcurrentHashMap<>();
+        ptyModes = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener, Signal... signals) {
+        addSignalListener(listener, Arrays.asList(ValidateUtils.checkNotNullAndNotEmpty(signals, "No signals")));
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener) {
+        addSignalListener(listener, Signal.SIGNALS);
+    }
+
+    /*
+     * NOTE: we don't care if the collection is a Set or not - after all,
+     * we hold the listeners inside a Set, so even if we add several times
+     * the same listener to the same signal set, it is harmless
+     */
+    @Override
+    public void addSignalListener(SignalListener listener, Collection<Signal> signals) {
+        ValidateUtils.checkNotNull(listener, "No listener instance");
+        ValidateUtils.checkNotNullAndNotEmpty(signals, "No signals");
+
+        for (Signal s : signals) {
+            getSignalListeners(s, true).add(listener);
+        }
+    }
+
+    @Override
+    public Map<String, String> getEnv() {
+        return env;
+    }
+
+    @Override
+    public Map<PtyMode, Integer> getPtyModes() {
+        return ptyModes;
+    }
+
+    @Override
+    public void removeSignalListener(SignalListener listener) {
+        ValidateUtils.checkNotNull(listener, "No listener instance");
+        for (Signal s : Signal.SIGNALS) {
+            Set<SignalListener> ls = getSignalListeners(s, false);
+            if (ls != null) {
+                ls.remove(listener);
+            }
+        }
+    }
+
+    public void signal(Signal signal) {
+        Set<SignalListener> ls = getSignalListeners(signal, false);
+        if (log.isDebugEnabled()) {
+            log.debug("signal({}) - listeners={}", signal, ls);
+        }
+
+        if (GenericUtils.isEmpty(ls)) {
+            return;
+        }
+
+        for (SignalListener l : ls) {
+            try {
+                l.signal(signal);
+
+                if (log.isTraceEnabled()) {
+                    log.trace("Signal {} to {}", signal, l);
+                }
+            } catch (RuntimeException e) {
+                log.warn("Failed ({}) to signal {} to listener={}: {}",
+                         e.getClass().getSimpleName(), signal, l, e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * adds a variable to the environment. This method is called <code>set</code>
+     * according to the name of the appropriate posix command <code>set</code>
+     *
+     * @param key   environment variable name
+     * @param value environment variable value
+     */
+    public void set(String key, String value) {
+        // TODO: listening for property changes would be nice too.
+        getEnv().put(key, value);
+    }
+
+    /**
+     * Retrieves the set of listeners registered for a signal
+     *
+     * @param signal The specified {@link Signal}
+     * @param create If {@code true} and no current listeners are mapped then
+     *               creates a new {@link Set}
+     * @return The {@link Set} of listeners registered for the signal - may be
+     * {@code null} in case <tt>create</tt> is {@code false}
+     */
+    protected Set<SignalListener> getSignalListeners(Signal signal, boolean create) {
+        Set<SignalListener> ls = listeners.get(signal);
+        if ((ls == null) && create) {
+            synchronized (listeners) {
+                ls = listeners.get(signal);
+                if (ls == null) {
+                    ls = new CopyOnWriteArraySet<>();
+                    listeners.put(signal, ls);
+                }
+            }
+        }
+
+        return ls;
+    }
+
+    @Override
+    public String toString() {
+        return "env=" + getEnv() + ", modes=" + getPtyModes();
+    }
+}
\ No newline at end of file