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 2018/09/06 16:03:27 UTC
[17/51] [abbrv] mina-sshd git commit: [SSHD-842] Split common
utilities code from sshd-core into sshd-common (new artifact)
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactoriesManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactoriesManager.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactoriesManager.java
deleted file mode 100644
index c9d876a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactoriesManager.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.signature;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.NamedResource;
-import org.apache.sshd.common.util.GenericUtils;
-import org.apache.sshd.common.util.ValidateUtils;
-
-/**
- * Manage the list of named factories for <code>Signature</code>.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public interface SignatureFactoriesManager {
- /**
- * @return The list of named <code>Signature</code> factories
- */
- List<NamedFactory<Signature>> getSignatureFactories();
-
- default String getSignatureFactoriesNameList() {
- return NamedResource.getNames(getSignatureFactories());
- }
-
- default List<String> getSignatureFactoriesNames() {
- return NamedResource.getNameList(getSignatureFactories());
- }
-
- void setSignatureFactories(List<NamedFactory<Signature>> factories);
-
- default void setSignatureFactoriesNameList(String names) {
- setSignatureFactoriesNames(GenericUtils.split(names, ','));
- }
-
- default void setSignatureFactoriesNames(String... names) {
- setSignatureFactoriesNames(GenericUtils.isEmpty((Object[]) names) ? Collections.emptyList() : Arrays.asList(names));
- }
-
- default void setSignatureFactoriesNames(Collection<String> names) {
- BuiltinSignatures.ParseResult result = BuiltinSignatures.parseSignatureList(names);
- @SuppressWarnings({ "rawtypes", "unchecked" })
- List<NamedFactory<Signature>> factories =
- (List) ValidateUtils.checkNotNullAndNotEmpty(result.getParsedFactories(), "No supported signature factories: %s", names);
- Collection<String> unsupported = result.getUnsupportedFactories();
- ValidateUtils.checkTrue(GenericUtils.isEmpty(unsupported), "Unsupported signature factories found: %s", unsupported);
- setSignatureFactories(factories);
- }
-
- /**
- * Attempts to use the primary manager's signature factories if not {@code null}/empty,
- * otherwise uses the secondary ones (regardless of whether there are any...)
- *
- * @param primary The primary {@link SignatureFactoriesManager}
- * @param secondary The secondary {@link SignatureFactoriesManager}
- * @return The resolved signature factories - may be {@code null}/empty
- * @see #getSignatureFactories(SignatureFactoriesManager)
- */
- static List<NamedFactory<Signature>> resolveSignatureFactories(
- SignatureFactoriesManager primary, SignatureFactoriesManager secondary) {
- List<NamedFactory<Signature>> factories = getSignatureFactories(primary);
- return GenericUtils.isEmpty(factories) ? getSignatureFactories(secondary) : factories;
- }
-
- /**
- * @param manager The {@link SignatureFactoriesManager} instance - ignored if {@code null}
- * @return The associated list of named <code>Signature</code> factories or {@code null} if
- * no manager instance
- */
- static List<NamedFactory<Signature>> getSignatureFactories(SignatureFactoriesManager manager) {
- return (manager == null) ? null : manager.getSignatureFactories();
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java
deleted file mode 100644
index 0881714..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureFactory.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.signature;
-
-import org.apache.sshd.common.BuiltinFactory;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-// CHECKSTYLE:OFF
-public interface SignatureFactory extends BuiltinFactory<Signature> {
- // nothing extra
-}
-//CHECKSTYLE:ON
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java b/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
deleted file mode 100644
index ad1d37e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/SignatureRSA.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.signature;
-
-import java.math.BigInteger;
-import java.security.PublicKey;
-import java.security.interfaces.RSAKey;
-import java.util.Map;
-
-import org.apache.sshd.common.keyprovider.KeyPairProvider;
-import org.apache.sshd.common.util.ValidateUtils;
-
-/**
- * RSA <code>Signature</code>
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- * @see <A HREF="https://tools.ietf.org/html/rfc4253#section-6.6">RFC4253 section 6.6</A>
- */
-public class SignatureRSA extends AbstractSignature {
- public static final String DEFAULT_ALGORITHM = "SHA1withRSA";
-
- private int verifierSignatureSize = -1;
-
- public SignatureRSA() {
- super(DEFAULT_ALGORITHM);
- }
-
- protected SignatureRSA(String algorithm) {
- super(algorithm);
- }
-
- /**
- * @return The expected number of bytes in the signature - non-positive
- * if not initialized or not intended to be used for verification
- */
- protected int getVerifierSignatureSize() {
- return verifierSignatureSize;
- }
-
- @Override
- public void initVerifier(PublicKey key) throws Exception {
- super.initVerifier(key);
- RSAKey rsaKey = ValidateUtils.checkInstanceOf(key, RSAKey.class, "Not an RSA key");
- verifierSignatureSize = getVerifierSignatureSize(rsaKey);
- }
-
- public static int getVerifierSignatureSize(RSAKey key) {
- BigInteger modulus = key.getModulus();
- return (modulus.bitLength() + Byte.SIZE - 1) / Byte.SIZE;
- }
-
- @Override
- public boolean verify(byte[] sig) throws Exception {
- byte[] data = sig;
- Map.Entry<String, byte[]> encoding = extractEncodedSignature(data);
- if (encoding != null) {
- String keyType = encoding.getKey();
- ValidateUtils.checkTrue(KeyPairProvider.SSH_RSA.equals(keyType), "Mismatched key type: %s", keyType);
- data = encoding.getValue();
- }
-
- int expectedSize = getVerifierSignatureSize();
- ValidateUtils.checkTrue(expectedSize > 0, "Signature verification size has not been initialized");
- // Pad with zero if value is trimmed
- if (data.length < expectedSize) {
- byte[] pad = new byte[expectedSize];
- System.arraycopy(data, 0, pad, pad.length - data.length, data.length);
- data = pad;
- }
-
- return doVerify(data);
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/signature/package.html
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/signature/package.html b/sshd-core/src/main/java/org/apache/sshd/common/signature/package.html
deleted file mode 100644
index d1b16e4..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/signature/package.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- 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.
--->
-<html>
-<head>
-</head>
-<body>
-
-<a href="{@docRoot}/org/apache/sshd/common/signature/Signature.html"><code>Signature</code></a> implementations.
-
-</body>
-</html>
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java
deleted file mode 100644
index 1620bad..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/EventListenerUtils.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * 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.util;
-
-import java.lang.reflect.Proxy;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EventListener;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class EventListenerUtils {
- /**
- * A special "comparator" whose only purpose is to ensure
- * there are no same references in a listener's set - to be used
- * in conjunction with a {@code TreeSet} as its comparator
- */
- @SuppressWarnings("checkstyle:anoninnerlength")
- public static final Comparator<EventListener> LISTENER_INSTANCE_COMPARATOR = (l1, l2) -> {
- if (l1 == l2) {
- return 0;
- } else if (l1 == null) {
- return 1;
- } else if (l2 == null) {
- return -1;
- }
-
- Class<?> c1 = l1.getClass();
- Class<?> c2 = l2.getClass();
- boolean checkHashCodes = true;
- if (Proxy.isProxyClass(c1)) {
- if (Proxy.isProxyClass(c2)) {
- checkHashCodes = false; // cannot call hashCode on a proxy
- } else {
- return 1;
- }
- } else if (Proxy.isProxyClass(c2)) {
- return -1;
- }
-
- if (checkHashCodes) {
- int nRes = Integer.compare(l1.hashCode(), l2.hashCode());
- if (nRes != 0) {
- return nRes;
- }
- }
-
- int nRes = Integer.compare(System.identityHashCode(l1), System.identityHashCode(l2));
- if (nRes != 0) {
- return nRes;
- }
-
- if (c1 != c2) {
- return c1.getName().compareTo(c2.getName());
- }
-
- String s1 = Objects.toString(l1.toString(), "");
- String s2 = Objects.toString(l2.toString(), "");
- nRes = s1.compareTo(s2);
- if (nRes != 0) {
- return nRes;
- }
- throw new UnsupportedOperationException("Ran out of options to compare instance of " + s1 + " vs. " + s2);
- };
-
- private EventListenerUtils() {
- throw new UnsupportedOperationException("No instance");
- }
-
- /**
- * @param <L> Type of {@link SshdEventListener} contained in the set
- * @param listeners The listeners to pre-add to the create set - ignored
- * if (@code null}/empty
- * @return A (synchronized) {@link Set} for containing the listeners ensuring
- * that if same listener instance is added repeatedly only <U>one</U>
- * instance is actually contained
- */
- public static <L extends SshdEventListener> Set<L> synchronizedListenersSet(Collection<? extends L> listeners) {
- Set<L> s = EventListenerUtils.synchronizedListenersSet();
- if (GenericUtils.size(listeners) > 0) {
- s.addAll(listeners);
- }
-
- return s;
- }
-
- /**
- * @param <L> Type of {@link SshdEventListener} contained in the set
- * @return A (synchronized) {@link Set} for containing the listeners ensuring
- * that if same listener instance is added repeatedly only <U>one</U>
- * instance is actually contained
- * @see #LISTENER_INSTANCE_COMPARATOR
- */
- public static <L extends SshdEventListener> Set<L> synchronizedListenersSet() {
- return Collections.synchronizedSet(new TreeSet<L>(LISTENER_INSTANCE_COMPARATOR));
- }
-
- /**
- * Provides proxy wrapper around an {@link Iterable} container of listener
- * interface implementation. <b>Note:</b> a listener interface is one whose
- * invoked methods return <u>only</u> {@code void}.
- *
- * @param <T> Generic listener type
- * @param listenerType The expected listener <u>interface</u>
- * @param listeners An {@link Iterable} container of listeners to be invoked.
- * <p>
- * <b>Note(s):</b>
- * </p>
- * <ul>
- * <li><p>
- * The invocation order is same as the {@link Iterable} container
- * </p></li>
- *
- * <li><p>
- * If any of the invoked listener methods throws an exception, the
- * rest of the listener are <u>not</u> invoked and the exception is
- * propagated to the caller
- * </p></li>
- *
- * <li><p>
- * It is up to the <u>caller</u> to ensure that the container does
- * not change while the proxy is invoked
- * </p></li>
- * </ul>
- * @return A proxy wrapper implementing the same interface, but delegating
- * the calls to the container
- * @see #proxyWrapper(Class, ClassLoader, Iterable)
- */
- public static <T extends SshdEventListener> T proxyWrapper(Class<T> listenerType, Iterable<? extends T> listeners) {
- return proxyWrapper(listenerType, listenerType.getClassLoader(), listeners);
- }
-
- /**
- * Provides proxy wrapper around an {@link Iterable} container of listener
- * interface implementation. <b>Note:</b> a listener interface is one whose
- * invoked methods return <u>only</u> {@code void}.
- *
- * @param <T> Generic {@link SshdEventListener} type
- * @param listenerType The expected listener <u>interface</u>
- * @param loader The {@link ClassLoader} to use for the proxy
- * @param listeners An {@link Iterable} container of listeners to be invoked.
- * <p>
- * <b>Note(s):</b>
- * </p>
- * <ul>
- * <li><p>
- * The invocation order is same as the {@link Iterable} container
- * </p></li>
- *
- * <li><p>
- * If any of the invoked listener methods throws an exception, the
- * rest of the listener are <u>not</u> invoked and the exception is
- * propagated to the caller
- * </p></li>
- *
- * <li><p>
- * It is up to the <u>caller</u> to ensure that the container does
- * not change while the proxy is invoked
- * </p></li>
- * </ul>
- * @return A proxy wrapper implementing the same interface, but delegating
- * the calls to the container
- * @throws IllegalArgumentException if <tt>listenerType</tt> is not an interface
- * or a {@code null} container has been provided
- * @see #proxyWrapper(Class, ClassLoader, Iterable)
- */
- public static <T extends SshdEventListener> T proxyWrapper(Class<T> listenerType, ClassLoader loader, final Iterable<? extends T> listeners) {
- Objects.requireNonNull(listenerType, "No listener type specified");
- ValidateUtils.checkTrue(listenerType.isInterface(), "Target proxy is not an interface: %s", listenerType.getSimpleName());
- Objects.requireNonNull(listeners, "No listeners container provided");
-
- Object wrapper = Proxy.newProxyInstance(loader, new Class<?>[]{listenerType}, (proxy, method, args) -> {
- Throwable err = null;
- for (T l : listeners) {
- try {
- method.invoke(l, args);
- } catch (Throwable t) {
- Throwable e = GenericUtils.peelException(t);
- err = GenericUtils.accumulateException(err, e);
- }
- }
-
- if (err != null) {
- throw err;
- }
-
- return null; // we assume always void return value...
- });
- return listenerType.cast(wrapper);
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/EventNotifier.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/EventNotifier.java b/sshd-core/src/main/java/org/apache/sshd/common/util/EventNotifier.java
deleted file mode 100644
index c041f1b..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/EventNotifier.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.util;
-
-/**
- * Notify about the occurrence of an event
- *
- * @param <E> type of event being notified
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface EventNotifier<E> {
- /**
- * @param event The event
- * @throws Exception If failed to process the event notification
- */
- void notifyEvent(E event) throws Exception;
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
deleted file mode 100644
index c924d1e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/GenericUtils.java
+++ /dev/null
@@ -1,915 +0,0 @@
-/*
- * 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.util;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.UndeclaredThrowableException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.ExecutionException;
-import java.util.function.BinaryOperator;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.function.Supplier;
-import java.util.stream.Collector;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-
-import javax.management.MBeanException;
-import javax.management.ReflectionException;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class GenericUtils {
-
- public static final byte[] EMPTY_BYTE_ARRAY = {};
- public static final char[] EMPTY_CHAR_ARRAY = {};
- public static final String[] EMPTY_STRING_ARRAY = {};
- public static final Object[] EMPTY_OBJECT_ARRAY = {};
-
- /**
- * A value indicating a {@code null} value - to be used as a placeholder
- * where {@code null}s are not allowed
- */
- public static final Object NULL = new Object();
-
- /**
- * The complement of {@link String#CASE_INSENSITIVE_ORDER}
- */
- public static final Comparator<String> CASE_SENSITIVE_ORDER = (s1, s2) -> {
- if (s1 == s2) {
- return 0;
- } else {
- return s1.compareTo(s2);
- }
- };
-
- public static final String QUOTES = "\"'";
-
- @SuppressWarnings("rawtypes")
- private static final Supplier CASE_INSENSITIVE_MAP_FACTORY = () -> new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-
- private GenericUtils() {
- throw new UnsupportedOperationException("No instance");
- }
-
- public static String trimToEmpty(String s) {
- if (s == null) {
- return "";
- } else {
- return s.trim();
- }
- }
-
- public static String replaceWhitespaceAndTrim(String s) {
- if (s != null) {
- s = s.replace('\t', ' ');
- }
-
- return trimToEmpty(s);
- }
-
- /**
- * @param s The {@link String} value to calculate the hash code on - may
- * be {@code null}/empty in which case a value of zero is returned
- * @return The calculated hash code
- * @see #hashCode(String, Boolean)
- */
- public static int hashCode(String s) {
- return hashCode(s, null);
- }
-
- /**
- * @param s The {@link String} value to calculate the hash code on - may
- * be {@code null}/empty in which case a value of zero is returned
- * @param useUppercase Whether to convert the string to uppercase, lowercase
- * or not at all:
- * <UL>
- * <LI>{@code null} - no conversion</LI>
- * <LI>{@link Boolean#TRUE} - get hash code of uppercase</LI>
- * <LI>{@link Boolean#FALSE} - get hash code of lowercase</LI>
- * </UL>
- * @return The calculated hash code
- */
- public static int hashCode(String s, Boolean useUppercase) {
- if (isEmpty(s)) {
- return 0;
- } else if (useUppercase == null) {
- return s.hashCode();
- } else if (useUppercase.booleanValue()) {
- return s.toUpperCase().hashCode();
- } else {
- return s.toLowerCase().hashCode();
- }
- }
-
- public static int safeCompare(String s1, String s2, boolean caseSensitive) {
- if (isSameReference(s1, s2)) {
- return 0;
- } else if (s1 == null) {
- return +1; // push null(s) to end
- } else if (s2 == null) {
- return -1; // push null(s) to end
- } else if (caseSensitive) {
- return s1.compareTo(s2);
- } else {
- return s1.compareToIgnoreCase(s2);
- }
- }
-
- public static <T> boolean isSameReference(T o1, T o2) {
- return o1 == o2;
- }
-
- public static int length(CharSequence cs) {
- return cs == null ? 0 : cs.length();
- }
-
- public static boolean isEmpty(CharSequence cs) {
- return length(cs) <= 0;
- }
-
- public static boolean isNotEmpty(CharSequence cs) {
- return !isEmpty(cs);
- }
-
- public static int indexOf(CharSequence cs, char c) {
- int len = length(cs);
- for (int pos = 0; pos < len; pos++) {
- char ch = cs.charAt(pos);
- if (ch == c) {
- return pos;
- }
- }
-
- return -1;
- }
-
- public static int lastIndexOf(CharSequence cs, char c) {
- int len = length(cs);
- for (int pos = len - 1; pos >= 0; pos--) {
- char ch = cs.charAt(pos);
- if (ch == c) {
- return pos;
- }
- }
-
- return -1;
- }
-
- // a List would be better, but we want to be compatible with String.split(...)
- public static String[] split(String s, char ch) {
- if (isEmpty(s)) {
- return EMPTY_STRING_ARRAY;
- }
-
- int lastPos = 0;
- int curPos = s.indexOf(ch);
- if (curPos < 0) {
- return new String[]{s};
- }
-
- Collection<String> values = new LinkedList<>();
- do {
- String v = s.substring(lastPos, curPos);
- values.add(v);
-
- // skip separator
- lastPos = curPos + 1;
- if (lastPos >= s.length()) {
- break;
- }
-
- curPos = s.indexOf(ch, lastPos);
- if (curPos < lastPos) {
- break; // no more separators
- }
- } while (curPos < s.length());
-
- // check if any leftovers
- if (lastPos < s.length()) {
- String v = s.substring(lastPos);
- values.add(v);
- }
-
- return values.toArray(new String[values.size()]);
- }
-
- public static <T> String join(T[] values, char ch) {
- return join(isEmpty(values) ? Collections.<T>emptyList() : Arrays.asList(values), ch);
- }
-
- public static String join(Iterable<?> iter, char ch) {
- return join((iter == null) ? null : iter.iterator(), ch);
- }
-
- public static String join(Iterator<?> iter, char ch) {
- if ((iter == null) || (!iter.hasNext())) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder();
- do { // we already asked hasNext...
- Object o = iter.next();
- if (sb.length() > 0) {
- sb.append(ch);
- }
- sb.append(Objects.toString(o));
- } while (iter.hasNext());
-
- return sb.toString();
- }
-
- public static <T> String join(T[] values, CharSequence sep) {
- return join(isEmpty(values) ? Collections.<T>emptyList() : Arrays.asList(values), sep);
- }
-
- public static String join(Iterable<?> iter, CharSequence sep) {
- return join((iter == null) ? null : iter.iterator(), sep);
- }
-
- public static String join(Iterator<?> iter, CharSequence sep) {
- if ((iter == null) || (!iter.hasNext())) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder();
- do { // we already asked hasNext...
- Object o = iter.next();
- if (sb.length() > 0) {
- sb.append(sep);
- }
- sb.append(Objects.toString(o));
- } while (iter.hasNext());
-
- return sb.toString();
- }
-
- public static int size(Collection<?> c) {
- return c == null ? 0 : c.size();
- }
-
- public static boolean isEmpty(Collection<?> c) {
- return (c == null) || c.isEmpty();
- }
-
- public static boolean isNotEmpty(Collection<?> c) {
- return !isEmpty(c);
- }
-
- public static int size(Map<?, ?> m) {
- return m == null ? 0 : m.size();
- }
-
- public static boolean isEmpty(Map<?, ?> m) {
- return (m == null) || m.isEmpty();
- }
-
- public static boolean isNotEmpty(Map<?, ?> m) {
- return !isEmpty(m);
- }
-
- @SafeVarargs
- public static <T> int length(T... a) {
- return a == null ? 0 : a.length;
- }
-
- public static <T> boolean isEmpty(Iterable<? extends T> iter) {
- if (iter == null) {
- return true;
- } else if (iter instanceof Collection<?>) {
- return isEmpty((Collection<?>) iter);
- } else {
- return isEmpty(iter.iterator());
- }
- }
-
- public static <T> boolean isNotEmpty(Iterable<? extends T> iter) {
- return !isEmpty(iter);
- }
-
- public static <T> boolean isEmpty(Iterator<? extends T> iter) {
- return iter == null || !iter.hasNext();
- }
-
- public static <T> boolean isNotEmpty(Iterator<? extends T> iter) {
- return !isEmpty(iter);
- }
-
- @SafeVarargs
- public static <T> boolean isEmpty(T... a) {
- return length(a) <= 0;
- }
-
- public static int length(char[] chars) {
- return (chars == null) ? 0 : chars.length;
- }
-
- public static boolean isEmpty(char[] chars) {
- return length(chars) <= 0;
- }
-
- /**
- * Compares 2 character arrays - <B>Note:</B> {@code null} and empty
- * are considered <U>equal</U>
- *
- * @param c1 1st array
- * @param c2 2nd array
- * @return Negative is 1st array comes first in lexicographical order,
- * positive if 2nd array comes first and zero if equal
- */
- public static int compare(char[] c1, char[] c2) {
- int l1 = length(c1);
- int l2 = length(c2);
- int cmpLen = Math.min(l1, l2);
- for (int index = 0; index < cmpLen; index++) {
- char c11 = c1[index];
- char c22 = c2[index];
- int nRes = Character.compare(c11, c22);
- if (nRes != 0) {
- return nRes;
- }
- }
-
- int nRes = Integer.compare(l1, l2);
- if (nRes != 0) {
- return nRes;
- }
-
- return 0;
- }
-
- @SafeVarargs // there is no EnumSet.of(...) so we have to provide our own
- public static <E extends Enum<E>> Set<E> of(E... values) {
- return of(isEmpty(values) ? Collections.emptySet() : Arrays.asList(values));
- }
-
- public static <E extends Enum<E>> Set<E> of(Collection<? extends E> values) {
- if (isEmpty(values)) {
- return Collections.emptySet();
- }
-
- Set<E> result = null;
- for (E v : values) {
- /*
- * A trick to compensate for the fact that we do not have
- * the enum Class to invoke EnumSet.noneOf
- */
- if (result == null) {
- result = EnumSet.of(v);
- } else {
- result.add(v);
- }
- }
-
- return result;
- }
-
- public static <T> boolean containsAny(Collection<? extends T> coll, Iterable<? extends T> values) {
- if (isEmpty(coll)) {
- return false;
- }
-
- for (T v : values) {
- if (coll.contains(v)) {
- return true;
- }
- }
-
- return false;
- }
-
- public static <T> void forEach(Iterable<T> values, Consumer<T> consumer) {
- if (isNotEmpty(values)) {
- values.forEach(consumer);
- }
- }
-
- public static <T, U> List<U> map(Collection<T> values, Function<? super T, ? extends U> mapper) {
- return stream(values).map(mapper).collect(Collectors.toList());
- }
-
- public static <T, U> NavigableSet<U> mapSort(
- Collection<T> values, Function<? super T, ? extends U> mapper, Comparator<U> comparator) {
- return stream(values).map(mapper).collect(toSortedSet(comparator));
- }
-
- public static <T, K, U> NavigableMap<K, U> toSortedMap(
- Iterable<T> values, Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, Comparator<K> comparator) {
- return stream(values).collect(toSortedMap(keyMapper, valueMapper, comparator));
- }
-
- public static <T, K, U> Collector<T, ?, NavigableMap<K, U>> toSortedMap(
- Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, Comparator<K> comparator) {
- return Collectors.toMap(keyMapper, valueMapper, throwingMerger(), () -> new TreeMap<>(comparator));
- }
-
- private static <T> BinaryOperator<T> throwingMerger() {
- return (u, v) -> {
- throw new IllegalStateException(String.format("Duplicate key %s", u));
- };
- }
-
- public static <T> Collector<T, ?, NavigableSet<T>> toSortedSet(Comparator<T> comparator) {
- return Collectors.toCollection(() -> new TreeSet<>(comparator));
- }
-
- public static <T> Stream<T> stream(Iterable<T> values) {
- if (isEmpty(values)) {
- return Stream.empty();
- } else if (values instanceof Collection<?>) {
- return ((Collection<T>) values).stream();
- } else {
- return StreamSupport.stream(values.spliterator(), false);
- }
- }
-
- @SafeVarargs
- public static <T> List<T> unmodifiableList(T... values) {
- return unmodifiableList(asList(values));
- }
-
- public static <T> List<T> unmodifiableList(Collection<? extends T> values) {
- if (isEmpty(values)) {
- return Collections.emptyList();
- } else {
- return Collections.unmodifiableList(new ArrayList<>(values));
- }
- }
-
- public static <T> List<T> unmodifiableList(Stream<T> values) {
- return unmodifiableList(values.collect(Collectors.toList()));
- }
-
- @SafeVarargs
- public static <T> List<T> asList(T... values) {
- return isEmpty(values) ? Collections.emptyList() : Arrays.asList(values);
- }
-
- @SafeVarargs
- public static <T> Set<T> asSet(T... values) {
- return new HashSet<>(asList(values));
- }
-
- @SafeVarargs
- public static <V extends Comparable<V>> NavigableSet<V> asSortedSet(V... values) {
- return asSortedSet(Comparator.naturalOrder(), values);
- }
-
- public static <V extends Comparable<V>> NavigableSet<V> asSortedSet(Collection<? extends V> values) {
- return asSortedSet(Comparator.naturalOrder(), values);
- }
-
- /**
- * @param <V> The element type
- * @param comp The (non-{@code null}) {@link Comparator} to use
- * @param values The values to be added (ignored if {@code null})
- * @return A {@link NavigableSet} containing the values (if any) sorted
- * using the provided comparator
- */
- @SafeVarargs
- public static <V> NavigableSet<V> asSortedSet(Comparator<? super V> comp, V... values) {
- return asSortedSet(comp, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
- }
-
- /**
- * @param <V> The element type
- * @param comp The (non-{@code null}) {@link Comparator} to use
- * @param values The values to be added (ignored if {@code null}/empty)
- * @return A {@link NavigableSet} containing the values (if any) sorted
- * using the provided comparator
- */
- public static <V> NavigableSet<V> asSortedSet(Comparator<? super V> comp, Collection<? extends V> values) {
- NavigableSet<V> set = new TreeSet<>(Objects.requireNonNull(comp, "No comparator"));
- if (size(values) > 0) {
- set.addAll(values);
- }
- return set;
- }
-
- /**
- * @param <V> Type of mapped value
- * @return A {@link Supplier} that returns a <U>new</U> {@link NavigableMap}
- * whenever its {@code get()} method is invoked
- */
- @SuppressWarnings("unchecked")
- public static <V> Supplier<NavigableMap<String, V>> caseInsensitiveMap() {
- return CASE_INSENSITIVE_MAP_FACTORY;
- }
-
- /**
- * Flips between keys and values of an input map
- *
- * @param <K> Original map key type
- * @param <V> Original map value type
- * @param <M> Flipped map type
- * @param map The original map to flip
- * @param mapCreator The creator of the target map
- * @param allowDuplicates Whether to ignore duplicates on flip
- * @return The flipped map result
- * @throws IllegalArgumentException if <tt>allowDuplicates</tt> is {@code false}
- * and a duplicate value found in the original map.
- */
- public static <K, V, M extends Map<V, K>> M flipMap(
- Map<? extends K, ? extends V> map, Supplier<? extends M> mapCreator, boolean allowDuplicates) {
- M result = Objects.requireNonNull(mapCreator.get(), "No map created");
- map.forEach((key, value) -> {
- K prev = result.put(value, key);
- if ((prev != null) && (!allowDuplicates)) {
- ValidateUtils.throwIllegalArgumentException("Multiple values for key=%s: current=%s, previous=%s", value, key, prev);
- }
- });
-
- return result;
- }
-
- @SafeVarargs
- public static <K, V, M extends Map<K, V>> M mapValues(
- Function<? super V, ? extends K> keyMapper, Supplier<? extends M> mapCreator, V... values) {
- return mapValues(keyMapper, mapCreator, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
- }
-
- /**
- * Creates a map out of a group of values
- *
- * @param <K> The key type
- * @param <V> The value type
- * @param <M> The result {@link Map} type
- * @param keyMapper The {@link Function} that generates a key for a given value.
- * If the returned key is {@code null} then the value is not mapped
- * @param mapCreator The {@link Supplier} used to create/retrieve the result map - provided
- * non-empty group of values
- * @param values The values to be mapped
- * @return The resulting {@link Map} - <B>Note:</B> no validation is made to ensure
- * that 2 (or more) values are not mapped to the same key
- */
- public static <K, V, M extends Map<K, V>> M mapValues(
- Function<? super V, ? extends K> keyMapper, Supplier<? extends M> mapCreator, Collection<? extends V> values) {
- M map = mapCreator.get();
- for (V v : values) {
- K k = keyMapper.apply(v);
- if (k == null) {
- continue; // debug breakpoint
- }
- map.put(k, v);
- }
-
- return map;
- }
-
- @SafeVarargs
- public static <T> T findFirstMatchingMember(Predicate<? super T> acceptor, T... values) {
- return findFirstMatchingMember(acceptor, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
- }
-
- public static <T> T findFirstMatchingMember(Predicate<? super T> acceptor, Collection<? extends T> values) {
- List<T> matches = selectMatchingMembers(acceptor, values);
- return GenericUtils.isEmpty(matches) ? null : matches.get(0);
- }
-
- /**
- * Returns a list of all the values that were accepted by a predicate
- *
- * @param <T> The type of value being evaluated
- * @param acceptor The {@link Predicate} to consult whether a member is selected
- * @param values The values to be scanned
- * @return A {@link List} of all the values that were accepted by the predicate
- */
- @SafeVarargs
- public static <T> List<T> selectMatchingMembers(Predicate<? super T> acceptor, T... values) {
- return selectMatchingMembers(acceptor, isEmpty(values) ? Collections.emptyList() : Arrays.asList(values));
- }
-
- /**
- * Returns a list of all the values that were accepted by a predicate
- *
- * @param <T> The type of value being evaluated
- * @param acceptor The {@link Predicate} to consult whether a member is selected
- * @param values The values to be scanned
- * @return A {@link List} of all the values that were accepted by the predicate
- */
- public static <T> List<T> selectMatchingMembers(Predicate<? super T> acceptor, Collection<? extends T> values) {
- return GenericUtils.stream(values)
- .filter(acceptor)
- .collect(Collectors.toList());
- }
-
- /**
- * @param s The {@link CharSequence} to be checked
- * @return If the sequence contains any of the {@link #QUOTES}
- * on <U>both</U> ends, then they are stripped, otherwise
- * nothing is done
- * @see #stripDelimiters(CharSequence, char)
- */
- public static CharSequence stripQuotes(CharSequence s) {
- if (isEmpty(s)) {
- return s;
- }
-
- for (int index = 0; index < QUOTES.length(); index++) {
- char delim = QUOTES.charAt(index);
- CharSequence v = stripDelimiters(s, delim);
- if (v != s) { // if stripped one don't continue
- return v;
- }
- }
-
- return s;
- }
-
- /**
- * @param s The {@link CharSequence} to be checked
- * @param delim The expected delimiter
- * @return If the sequence contains the delimiter on <U>both</U> ends,
- * then it is are stripped, otherwise nothing is done
- */
- public static CharSequence stripDelimiters(CharSequence s, char delim) {
- if (isEmpty(s) || (s.length() < 2)) {
- return s;
- }
-
- int lastPos = s.length() - 1;
- if ((s.charAt(0) != delim) || (s.charAt(lastPos) != delim)) {
- return s;
- } else {
- return s.subSequence(1, lastPos);
- }
- }
-
- public static RuntimeException toRuntimeException(Throwable t) {
- return toRuntimeException(t, true);
- }
-
- /**
- * Converts a thrown generic exception to a {@link RuntimeException}
- *
- * @param t The original thrown exception
- * @param peelThrowable Whether to determine the root cause by "peeling"
- * any enclosing exceptions
- * @return The thrown cause if already a runtime exception, otherwise a
- * runtime exception of the resolved exception as its cause
- * @see #peelException(Throwable)
- */
- public static RuntimeException toRuntimeException(Throwable t, boolean peelThrowable) {
- Throwable e = peelThrowable ? peelException(t) : t;
- if (e instanceof RuntimeException) {
- return (RuntimeException) e;
- }
-
- return new RuntimeException(e);
- }
-
- /**
- * Attempts to get to the "effective" exception being thrown,
- * by taking care of some known exceptions that wrap the original thrown
- * one.
- *
- * @param t The original {@link Throwable} - ignored if {@code null}
- * @return The effective exception - same as input if not a wrapper
- */
- public static Throwable peelException(Throwable t) {
- // NOTE: check order is important - e.g., InvocationTargetException extends ReflectiveOperationException
- if (t == null) {
- return t;
- } else if (t instanceof UndeclaredThrowableException) {
- Throwable wrapped = ((UndeclaredThrowableException) t).getUndeclaredThrowable();
- // according to the Javadoc it may be null, in which case 'getCause'
- // might contain the information we need
- if (wrapped != null) {
- return peelException(wrapped);
- }
-
- wrapped = t.getCause();
- if (wrapped != t) { // make sure it is a real cause
- return peelException(wrapped);
- }
- } else if (t instanceof InvocationTargetException) {
- Throwable target = ((InvocationTargetException) t).getTargetException();
- if (target != null) {
- return peelException(target);
- }
- } else if (t instanceof ReflectionException) {
- Throwable target = ((ReflectionException) t).getTargetException();
- if (target != null) {
- return peelException(target);
- }
- } else if (t instanceof ExecutionException) {
- Throwable wrapped = resolveExceptionCause(t);
- if (wrapped != null) {
- return peelException(wrapped);
- }
- } else if (t instanceof MBeanException) {
- Throwable target = ((MBeanException) t).getTargetException();
- if (target != null) {
- return peelException(target);
- }
- }
-
- return t; // no special handling required or available
- }
-
- /**
- * @param t The original {@link Throwable} - ignored if {@code null}
- * @return If {@link Throwable#getCause()} is non-{@code null} then
- * the cause, otherwise the original exception - {@code null} if
- * the original exception was {@code null}
- */
- public static Throwable resolveExceptionCause(Throwable t) {
- if (t == null) {
- return t;
- }
-
- Throwable c = t.getCause();
- if (c == null) {
- return t;
- } else {
- return c;
- }
- }
-
- /**
- * Used to "accumulate" exceptions of the <U>same type</U>. If the
- * current exception is {@code null} then the new one becomes the current,
- * otherwise the new one is added as a <U>suppressed</U> exception to the
- * current one
- *
- * @param <T> The exception type
- * @param current The current exception
- * @param extra The extra/new exception
- * @return The resolved exception
- * @see Throwable#addSuppressed(Throwable)
- */
- public static <T extends Throwable> T accumulateException(T current, T extra) {
- if (current == null) {
- return extra;
- }
-
- if ((extra == null) || (extra == current)) {
- return current;
- }
-
- current.addSuppressed(extra);
- return current;
- }
-
- public static IOException toIOException(Throwable e) {
- if (e instanceof IOException) {
- return (IOException) e;
- } else {
- return new IOException(e);
- }
- }
-
- /**
- * Wraps a value into a {@link Supplier}
- * @param <T> Type of value being supplied
- * @param value The value to be supplied
- * @return The supplier wrapper
- */
- public static <T> Supplier<T> supplierOf(T value) {
- return () -> value;
- }
-
- /**
- * Resolves to an always non-{@code null} iterator
- *
- * @param <T> Type of value being iterated
- * @param iterable The {@link Iterable} instance
- * @return A non-{@code null} iterator which may be empty if no iterable
- * instance or no iterator returned from it
- * @see #iteratorOf(Iterator)
- */
- public static <T> Iterator<T> iteratorOf(Iterable<T> iterable) {
- return iteratorOf((iterable == null) ? null : iterable.iterator());
- }
-
- /**
- * @param <B> Generic base class
- * @param <D> Generic child class
- * @return An identity {@link Function} that returns its input child class as a base class
- */
- public static <B, D extends B> Function<D, B> downcast() {
- return t -> t;
- }
-
- /**
- * Resolves to an always non-{@code null} iterator
- *
- * @param <T> Type of value being iterated
- * @param iter The {@link Iterator} instance
- * @return A non-{@code null} iterator which may be empty if no iterator instance
- * @see Collections#emptyIterator()
- */
- public static <T> Iterator<T> iteratorOf(Iterator<T> iter) {
- return (iter == null) ? Collections.emptyIterator() : iter;
- }
-
- public static <U, V> Iterable<V> wrapIterable(Iterable<? extends U> iter, Function<? super U, ? extends V> mapper) {
- return () -> wrapIterator(iter, mapper);
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static <U, V> Iterator<V> wrapIterator(Iterable<? extends U> iter, Function<? super U, ? extends V> mapper) {
- return (Iterator) stream(iter).map(mapper).iterator();
- }
-
- public static <U, V> Iterator<V> wrapIterator(Iterator<? extends U> iter, Function<? super U, ? extends V> mapper) {
- Iterator<? extends U> iterator = iteratorOf(iter);
- return new Iterator<V>() {
- @Override
- public boolean hasNext() {
- return iterator.hasNext();
- }
-
- @Override
- public V next() {
- U value = iterator.next();
- return mapper.apply(value);
- }
- };
- }
-
- /**
- * Wraps a group of {@link Supplier}s of {@link Iterable} instances into a "unified"
- * {@link Iterable} of their values, in the same order as the suppliers - i.e., once the values
- * from a specific supplier are exhausted, the next one is consulted, and so on, until all
- * suppliers have been consulted
- *
- * @param <T> Type of value being iterated
- * @param providers The providers - ignored if {@code null} (i.e., return an empty iterable instance)
- * @return The wrapping instance
- */
- public static <T> Iterable<T> multiIterableSuppliers(Iterable<? extends Supplier<? extends Iterable<? extends T>>> providers) {
- return () -> stream(providers).<T>flatMap(s -> stream(s.get())).map(Function.identity()).iterator();
- }
-
- public static <K, V> MapBuilder<K, V> mapBuilder() {
- return new MapBuilder<>();
- }
-
- public static <K, V> MapBuilder<K, V> mapBuilder(Comparator<K> comparator) {
- return new MapBuilder<>(comparator);
- }
-
- public static class MapBuilder<K, V> {
- private Map<K, V> map;
-
- public MapBuilder() {
- this.map = new LinkedHashMap<>();
- }
-
- public MapBuilder(Comparator<? super K> comparator) {
- this.map = new TreeMap<>(comparator);
- }
-
- public MapBuilder<K, V> put(K k, V v) {
- map.put(k, v);
- return this;
- }
-
- public Map<K, V> build() {
- return map;
- }
-
- public Map<K, V> immutable() {
- return Collections.unmodifiableMap(map);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/IgnoringEmptyMap.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/IgnoringEmptyMap.java b/sshd-core/src/main/java/org/apache/sshd/common/util/IgnoringEmptyMap.java
deleted file mode 100644
index 8f18bfe..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/IgnoringEmptyMap.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.util;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * A dummy map that ignores all {@code put/remove} calls
- *
- * @param <K> Key type
- * @param <V> Value type
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public class IgnoringEmptyMap<K, V> implements Map<K, V> {
- @SuppressWarnings("rawtypes")
- private static final IgnoringEmptyMap INSTANCE = new IgnoringEmptyMap();
-
- public IgnoringEmptyMap() {
- super();
- }
-
- @Override
- public int size() {
- return 0;
- }
-
- @Override
- public boolean isEmpty() {
- return true;
- }
-
- @Override
- public boolean containsValue(Object value) {
- Objects.requireNonNull(value, "No value provided");
- return false;
- }
-
- @Override
- public boolean containsKey(Object key) {
- Objects.requireNonNull(key, "No key provided");
- return false;
- }
-
- @Override
- public V get(Object key) {
- Objects.requireNonNull(key, "No key provided");
- return null;
- }
-
- @Override
- public V put(K key, V value) {
- Objects.requireNonNull(key, "No key provided");
- Objects.requireNonNull(value, "No value provided");
- return null;
- }
-
- @Override
- public V remove(Object key) {
- Objects.requireNonNull(key, "No key provided");
- return null;
- }
-
- @Override
- public void putAll(Map<? extends K, ? extends V> m) {
- // ignored
- }
-
- @Override
- public void clear() {
- // ignored
- }
-
- @Override
- public Set<K> keySet() {
- return Collections.emptySet();
- }
-
- @Override
- public Collection<V> values() {
- return Collections.emptyList();
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof IgnoringEmptyMap<?, ?>;
- }
-
- @Override
- public int hashCode() {
- return 0;
- }
-
- @Override
- public String toString() {
- return "{}";
- }
-
- @Override
- public Set<Entry<K, V>> entrySet() {
- return Collections.emptySet();
- }
-
- @SuppressWarnings("unchecked")
- public static <K, V> IgnoringEmptyMap<K, V> getInstance() {
- return INSTANCE;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java b/sshd-core/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java
deleted file mode 100644
index 490abb0..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/Int2IntFunction.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.util;
-
-import java.util.function.IntUnaryOperator;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class Int2IntFunction {
- private Int2IntFunction() {
- throw new UnsupportedOperationException("No instance");
- }
-
- public static IntUnaryOperator sub(int delta) {
- return add(0 - delta);
- }
-
- public static IntUnaryOperator add(int delta) {
- if (delta == 0) {
- return IntUnaryOperator.identity();
- } else {
- return value -> value + delta;
- }
- }
-
- public static IntUnaryOperator mul(int factor) {
- if (factor == 0) {
- return constant(0);
- } else if (factor == 1) {
- return IntUnaryOperator.identity();
- } else {
- return value -> value * factor;
- }
- }
-
- public static IntUnaryOperator constant(int v) {
- return value -> v;
- }
-
- public static IntUnaryOperator div(int factor) {
- if (factor == 1) {
- return IntUnaryOperator.identity();
- } else {
- ValidateUtils.checkTrue(factor != 0, "Zero division factor");
- return value -> value / factor;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/Invoker.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/Invoker.java b/sshd-core/src/main/java/org/apache/sshd/common/util/Invoker.java
deleted file mode 100644
index 71cbebd..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/Invoker.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.util;
-
-import java.util.AbstractMap.SimpleImmutableEntry;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * The complement to the {@code Callable} interface - accepts one argument
- * and possibly throws somethind
- *
- * @param <ARG> Argument type
- * @param <RET> Return type
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface Invoker<ARG, RET> {
- RET invoke(ARG arg) throws Throwable;
-
- static <ARG> Invoker<ARG, Void> wrapAll(Collection<? extends Invoker<? super ARG, ?>> invokers) {
- return arg -> {
- invokeAll(arg, invokers);
- return null;
- };
- }
-
- /**
- * Invokes <U>all</U> the instances ignoring the return value. Any
- * intermediate exceptions are accumulated and thrown at the end.
- *
- * @param <ARG> Argument type
- * @param arg The argument to pass to the {@link #invoke(Object)} method
- * @param invokers The invokers to scan - ignored if {@code null}/empty
- * (also ignores {@code null} members)
- * @throws Throwable If invocation failed
- */
- static <ARG> void invokeAll(ARG arg, Collection<? extends Invoker<? super ARG, ?>> invokers) throws Throwable {
- if (GenericUtils.isEmpty(invokers)) {
- return;
- }
-
- Throwable err = null;
- for (Invoker<? super ARG, ?> i : invokers) {
- if (i == null) {
- continue;
- }
-
- try {
- i.invoke(arg);
- } catch (Throwable t) {
- err = GenericUtils.accumulateException(err, t);
- }
- }
-
- if (err != null) {
- throw err;
- }
- }
-
- static <ARG> Invoker<ARG, Void> wrapFirst(Collection<? extends Invoker<? super ARG, ?>> invokers) {
- return arg -> {
- Map.Entry<Invoker<? super ARG, ?>, Throwable> result = invokeTillFirstFailure(arg, invokers);
- if (result != null) {
- throw result.getValue();
- }
- return null;
- };
- }
-
- /**
- * Invokes all instances until 1st failure (if any)
- *
- * @param <ARG> Argument type
- * @param arg The argument to pass to the {@link #invoke(Object)} method
- * @param invokers The invokers to scan - ignored if {@code null}/empty
- * (also ignores {@code null} members)
- * @return A {@link SimpleImmutableEntry} representing the <U>first</U> failed
- * invocation - {@code null} if all were successful (or none invoked).
- */
- static <ARG> SimpleImmutableEntry<Invoker<? super ARG, ?>, Throwable> invokeTillFirstFailure(ARG arg, Collection<? extends Invoker<? super ARG, ?>> invokers) {
- if (GenericUtils.isEmpty(invokers)) {
- return null;
- }
-
- for (Invoker<? super ARG, ?> i : invokers) {
- if (i == null) {
- continue;
- }
-
- try {
- i.invoke(arg);
- } catch (Throwable t) {
- return new SimpleImmutableEntry<>(i, t);
- }
- }
-
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java
deleted file mode 100644
index 6bcc93a..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/MapEntryUtils.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.util;
-
-import java.util.Comparator;
-import java.util.Map;
-
-/**
- * Represents an un-modifiable pair of values
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class MapEntryUtils {
- @SuppressWarnings({"rawtypes", "unchecked"})
- private static final Comparator<Map.Entry<Comparable, ?>> BY_KEY_COMPARATOR = (o1, o2) -> {
- Comparable k1 = o1.getKey();
- Comparable k2 = o2.getKey();
- return k1.compareTo(k2);
- };
-
- private MapEntryUtils() {
- throw new UnsupportedOperationException("No instance");
- }
-
- /**
- * @param <K> The {@link Comparable} key type
- * @param <V> The associated entry value
- * @return A {@link Comparator} for {@link java.util.Map.Entry}-ies that
- * compares the key values
- */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static <K extends Comparable<K>, V> Comparator<Map.Entry<K, V>> byKeyEntryComparator() {
- return (Comparator) BY_KEY_COMPARATOR;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/NumberUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/NumberUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/NumberUtils.java
deleted file mode 100644
index b1aed93..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/NumberUtils.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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.util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.IntStream;
-
-/**
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class NumberUtils {
- /**
- * A {@link List} of all the {@link Class} types used to represent the
- * primitive numerical values
- */
- public static final List<Class<?>> NUMERIC_PRIMITIVE_CLASSES =
- GenericUtils.unmodifiableList(
- Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE,
- Float.TYPE, Double.TYPE
- );
-
- /**
- * A {@link List} containing all the pure powers of 2 for a {@code long}
- * value. The value at index <I>n</I> is 2 to the power of <I>n</I>
- */
- public static final List<Long> POWERS_OF_TWO =
- GenericUtils.unmodifiableList(IntStream.range(0, 64)
- .mapToObj(i -> 1L << i));
-
- private NumberUtils() {
- throw new UnsupportedOperationException("No instance");
- }
-
- public static boolean isPowerOf2(long value) {
- for (Long l : POWERS_OF_TWO) {
- if (value == l) {
- return true;
- }
- }
-
- return false;
- }
-
- public static long getNextPowerOf2(long value) {
- long j = 1L;
- while (j < value) {
- j <<= 1;
- }
- return j;
- }
-
- public static int getNextPowerOf2(int value) {
- int j = 1;
- while (j < value) {
- j <<= 1;
- }
- return j;
- }
-
- public static int hashCode(long... values) {
- return Arrays.hashCode(values);
- }
-
- public static int hashCode(int... values) {
- return Arrays.hashCode(values);
- }
-
- public static int hashCode(byte... values) {
- return Arrays.hashCode(values);
- }
-
- public static int hashCode(byte[] a, int offset, int len) {
- if (len == 0) {
- return 0;
- }
-
- int result = 1;
- for (int pos = offset, count = 0; count < len; pos++, count++) {
- byte element = a[pos];
- result = 31 * result + element;
- }
-
- return result;
- }
-
- public static int diffOffset(byte[] a1, int startPos1, byte[] a2, int startPos2, int len) {
- for (int pos1 = startPos1, pos2 = startPos2, count = 0; count < len; pos1++, pos2++, count++) {
- byte v1 = a1[pos1];
- byte v2 = a2[pos2];
- if (v1 != v2) {
- return count;
- }
- }
-
- return -1;
- }
-
- /**
- * @param clazz The {@link Class} to examine - ignored if {@code null}
- * @return If the class is a {@link Number} or one of the primitive numerical types
- * @see #NUMERIC_PRIMITIVE_CLASSES
- */
- public static boolean isNumericClass(Class<?> clazz) {
- if (clazz == null) {
- return false;
- }
-
- // turns out that the primitive types are not assignable to Number
- if (Number.class.isAssignableFrom(clazz)) {
- return true;
- }
-
- return NUMERIC_PRIMITIVE_CLASSES.indexOf(clazz) >= 0;
- }
-
- /**
- * Converts a {@link Number} into an {@link Integer} if not already such
- *
- * @param n The {@link Number} - ignored if {@code null}
- * @return The equivalent {@link Integer} value
- */
- public static Integer toInteger(Number n) {
- if (n == null) {
- return null;
- } else if (n instanceof Integer) {
- return (Integer) n;
- } else {
- return n.intValue();
- }
- }
-
- public static String join(CharSequence separator, long... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (long v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(v);
- }
-
- return sb.toString();
- }
-
- public static String join(char separator, long... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (long v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(v);
- }
-
- return sb.toString();
- }
-
- public static String join(CharSequence separator, boolean unsigned, byte... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (byte v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(unsigned ? (v & 0xFF) : v);
- }
-
- return sb.toString();
- }
-
- public static String join(char separator, boolean unsigned, byte... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (byte v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(unsigned ? (v & 0xFF) : v);
- }
-
- return sb.toString();
- }
-
- public static String join(CharSequence separator, int... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (int v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(v);
- }
-
- return sb.toString();
- }
-
- public static String join(char separator, int... values) {
- if (NumberUtils.isEmpty(values)) {
- return "";
- }
-
- StringBuilder sb = new StringBuilder(values.length * Byte.SIZE);
- for (int v : values) {
- if (sb.length() > 0) {
- sb.append(separator);
- }
- sb.append(v);
- }
-
- return sb.toString();
- }
-
- public static boolean isEmpty(byte[] a) {
- return NumberUtils.length(a) <= 0;
- }
-
- public static boolean isEmpty(int[] a) {
- return NumberUtils.length(a) <= 0;
- }
-
- public static boolean isEmpty(long[] a) {
- return NumberUtils.length(a) <= 0;
- }
-
- public static int length(byte... a) {
- return a == null ? 0 : a.length;
- }
-
- public static int length(int... a) {
- return a == null ? 0 : a.length;
- }
-
- public static int length(long... a) {
- return a == null ? 0 : a.length;
- }
-
- public static List<Integer> asList(int... values) {
- int len = length(values);
- if (len <= 0) {
- return Collections.emptyList();
- }
-
- List<Integer> l = new ArrayList<>(len);
- for (int v : values) {
- l.add(v);
- }
-
- return l;
- }
-
- /**
- * Checks if optional sign and all others are '0'-'9'
- * @param cs The {@link CharSequence} to check
- * @return {@code true} if valid integer number
- */
- public static boolean isIntegerNumber(CharSequence cs) {
- if (GenericUtils.isEmpty(cs)) {
- return false;
- }
-
- for (int index = 0; index < cs.length(); index++) {
- char c = cs.charAt(0);
- if ((c >= '0') && (c <= '9')) {
- continue;
- }
-
- if ((c == '+') || (c == '-')) {
- if (index == 0) {
- continue;
- }
- }
-
- return false;
- }
-
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/ObjectBuilder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/ObjectBuilder.java b/sshd-core/src/main/java/org/apache/sshd/common/util/ObjectBuilder.java
deleted file mode 100644
index 23884a2..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/ObjectBuilder.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.util;
-
-import java.util.function.Supplier;
-
-/**
- * A generic builder interface
- *
- * @param <T> Type of object being built
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-@FunctionalInterface
-public interface ObjectBuilder<T> extends Supplier<T> {
- @Override
- default T get() {
- return build();
- }
-
- T build();
-}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/10de190e/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
deleted file mode 100644
index f0b2c7e..0000000
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/OsUtils.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.util;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Operating system dependent utility methods.
- *
- * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
- */
-public final class OsUtils {
-
- /**
- * Property that can be used to override the reported value from {@link #getCurrentUser()}.
- * If not set then "user.name" system property is used
- */
- public static final String CURRENT_USER_OVERRIDE_PROP = "org.apache.sshd.currentUser";
-
- /**
- * Property that can be used to override the reported value from {@link #getJavaVersion()}.
- * If not set then "java.version" system property is used
- */
- public static final String JAVA_VERSION_OVERRIDE_PROP = "org.apache.sshd.javaVersion";
-
- /**
- * Property that can be used to override the reported value from {@link #isWin32()}.
- * If not set then "os.name" system property is used
- */
- public static final String OS_TYPE_OVERRIDE_PROP = "org.apache.sshd.osType";
-
- public static final String WINDOWS_SHELL_COMMAND_NAME = "cmd.exe";
- public static final String LINUX_SHELL_COMMAND_NAME = "/bin/sh";
-
- public static final String ROOT_USER = "root";
-
- public static final List<String> LINUX_COMMAND =
- Collections.unmodifiableList(Arrays.asList(LINUX_SHELL_COMMAND_NAME, "-i", "-l"));
- public static final List<String> WINDOWS_COMMAND =
- Collections.unmodifiableList(Collections.singletonList(WINDOWS_SHELL_COMMAND_NAME));
-
- private static final AtomicReference<String> CURRENT_USER_HOLDER = new AtomicReference<>(null);
- private static final AtomicReference<VersionInfo> JAVA_VERSION_HOLDER = new AtomicReference<>(null);
- private static final AtomicReference<Boolean> OS_TYPE_HOLDER = new AtomicReference<>(null);
-
- private OsUtils() {
- throw new UnsupportedOperationException("No instance allowed");
- }
-
- /**
- * @return true if the host is a UNIX system (and not Windows).
- */
- public static boolean isUNIX() {
- return !isWin32();
- }
-
- /**
- * @return true if the host is Windows (and not UNIX).
- * @see #OS_TYPE_OVERRIDE_PROP
- * @see #setWin32(Boolean)
- */
- public static boolean isWin32() {
- Boolean typeValue;
- synchronized (OS_TYPE_HOLDER) {
- typeValue = OS_TYPE_HOLDER.get();
- if (typeValue != null) { // is it the 1st time
- return typeValue;
- }
-
- String value = System.getProperty(OS_TYPE_OVERRIDE_PROP, System.getProperty("os.name"));
- typeValue = GenericUtils.trimToEmpty(value).toLowerCase().contains("windows");
- OS_TYPE_HOLDER.set(typeValue);
- }
-
- return typeValue;
- }
-
- /**
- * Can be used to enforce Win32 or Linux report from {@link #isWin32()} or {@link #isUNIX()}
- * @param win32 The value to set - if {@code null} then O/S type is auto-detected
- * @see #isWin32()
- */
- public static void setWin32(Boolean win32) {
- synchronized (OS_TYPE_HOLDER) {
- OS_TYPE_HOLDER.set(win32);
- }
- }
-
- public static List<String> resolveDefaultInteractiveCommand() {
- return resolveInteractiveCommand(isWin32());
- }
-
- public static List<String> resolveInteractiveCommand(boolean isWin32) {
- if (isWin32) {
- return WINDOWS_COMMAND;
- } else {
- return LINUX_COMMAND;
- }
- }
-
- /**
- * Get current user name
- *
- * @return Current user
- * @see #CURRENT_USER_OVERRIDE_PROP
- */
- public static String getCurrentUser() {
- String username = null;
- synchronized (CURRENT_USER_HOLDER) {
- username = CURRENT_USER_HOLDER.get();
- if (username != null) { // have we already resolved it ?
- return username;
- }
-
- username = getCanonicalUser(System.getProperty(CURRENT_USER_OVERRIDE_PROP, System.getProperty("user.name")));
- ValidateUtils.checkNotNullAndNotEmpty(username, "No username available");
- CURRENT_USER_HOLDER.set(username);
- }
-
- return username;
- }
-
- /**
- * Remove {@code Windows} domain and/or group prefix as well as "(User);" suffix
- *
- * @param user The original username - ignored if {@code null}/empty
- * @return The canonical user - unchanged if {@code Unix} O/S
- */
- public static String getCanonicalUser(String user) {
- if (GenericUtils.isEmpty(user)) {
- return user;
- }
-
- // Windows owner sometime has the domain and/or group prepended to it
- if (isWin32()) {
- int pos = user.lastIndexOf('\\');
- if (pos > 0) {
- user = user.substring(pos + 1);
- }
-
- pos = user.indexOf(' ');
- if (pos > 0) {
- user = user.substring(0, pos).trim();
- }
- }
-
- return user;
- }
-
- /**
- * Attempts to resolve canonical group name for {@code Windows}
- *
- * @param group The original group name - used if not {@code null}/empty
- * @param user The owner name - sometimes it contains a group name
- * @return The canonical group name
- */
- public static String resolveCanonicalGroup(String group, String user) {
- if (isUNIX()) {
- return group;
- }
-
- // we reach this code only for Windows
- if (GenericUtils.isEmpty(group)) {
- int pos = GenericUtils.isEmpty(user) ? -1 : user.lastIndexOf('\\');
- return (pos > 0) ? user.substring(0, pos) : group;
- }
-
- int pos = group.indexOf(' ');
- return (pos < 0) ? group : group.substring(0, pos).trim();
- }
-
- /**
- * Can be used to programmatically set the username reported by {@link #getCurrentUser()}
- * @param username The username to set - if {@code null} then {@link #CURRENT_USER_OVERRIDE_PROP}
- * will be consulted
- */
- public static void setCurrentUser(String username) {
- synchronized (CURRENT_USER_HOLDER) {
- CURRENT_USER_HOLDER.set(username);
- }
- }
-
- /**
- * Resolves the reported Java version by consulting {@link #JAVA_VERSION_OVERRIDE_PROP}.
- * If not set, then "java.version" property is used
- * @return The resolved {@link VersionInfo} - never {@code null}
- * @see #setJavaVersion(VersionInfo)
- */
- public static VersionInfo getJavaVersion() {
- VersionInfo version;
- synchronized (JAVA_VERSION_HOLDER) {
- version = JAVA_VERSION_HOLDER.get();
- if (version != null) { // first time ?
- return version;
- }
-
- String value = System.getProperty(JAVA_VERSION_OVERRIDE_PROP, System.getProperty("java.version"));
- // e.g.: 1.7.5_30
- value = ValidateUtils.checkNotNullAndNotEmpty(value, "No configured Java version value").replace('_', '.');
- // clean up any non-digits - in case something like 1.6.8_25-b323
- for (int index = 0; index < value.length(); index++) {
- char ch = value.charAt(index);
- if ((ch == '.') || ((ch >= '0') && (ch <= '9'))) {
- continue;
- }
-
- value = value.substring(0, index);
- break;
- }
-
- version = ValidateUtils.checkNotNull(VersionInfo.parse(value), "No version parsed for %s", value);
- JAVA_VERSION_HOLDER.set(version);
- }
-
- return version;
- }
-
- /**
- * Set programmatically the reported Java version
- * @param version The version - if {@code null} then it will be automatically resolved
- */
- public static void setJavaVersion(VersionInfo version) {
- synchronized (JAVA_VERSION_HOLDER) {
- JAVA_VERSION_HOLDER.set(version);
- }
- }
-
- /**
- * @param path The original path
- * @return A path that can be compared with another one where case
- * sensitivity of the underlying O/S has been taken into account -
- * never {@code null}
- */
- public static String getComparablePath(String path) {
- String p = (path == null) ? "" : path;
- return isWin32() ? p.toLowerCase() : p;
- }
-}