This is an automated email from the ASF dual-hosted git repository. twolf pushed a commit to branch dev_3.0 in repository https://gitbox.apache.org/repos/asf/mina-sshd.git
commit c263dc583012df9de4e9a85820dddb7bfe11315c Author: Thomas Wolf <tw...@apache.org> AuthorDate: Sat Apr 5 21:18:17 2025 +0200 Simplify invoking ChannelListeners Remove the now unused Invoker interface. --- .../apache/sshd/common/util/ExceptionUtils.java | 13 ++ .../sshd/common/util/io/functors/Invoker.java | 140 --------------------- .../sshd/common/channel/AbstractChannel.java | 87 ++----------- 3 files changed, 25 insertions(+), 215 deletions(-) diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java b/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java index 0e8016a0a..d3060cf60 100644 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java +++ b/sshd-common/src/main/java/org/apache/sshd/common/util/ExceptionUtils.java @@ -20,6 +20,7 @@ package org.apache.sshd.common.util; import java.io.IOException; +import java.io.UncheckedIOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.UndeclaredThrowableException; import java.util.concurrent.ExecutionException; @@ -47,6 +48,18 @@ public final class ExceptionUtils { } } + public static void rethrowAsRuntimeException(Throwable e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } else if (e instanceof Error) { + throw (Error) e; + } else if (e instanceof IOException) { + throw new UncheckedIOException((IOException) e); + } else { + throw new UncheckedIOException(new IOException(e)); + } + } + /** * 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 diff --git a/sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java b/sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java deleted file mode 100644 index cf9f0baa2..000000000 --- a/sshd-common/src/main/java/org/apache/sshd/common/util/io/functors/Invoker.java +++ /dev/null @@ -1,140 +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.io.functors; - -import java.util.AbstractMap.SimpleImmutableEntry; -import java.util.Collection; -import java.util.Map; - -import org.apache.sshd.common.util.ExceptionUtils; -import org.apache.sshd.common.util.GenericUtils; - -/** - * The complement to the {@code Callable} interface - accepts one argument and possibly throws something - * - * @param <ARG> Argument type - * @param <RET> Return type - * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> - */ -@FunctionalInterface -public interface Invoker<ARG, RET> { - RET invoke(ARG arg) throws Throwable; - - /** - * Wraps a bunch of {@link Invoker}-s that return no value into one that invokes them in the same <U>order</U> as - * they appear. <B>Note:</B> <U>all</U> invokers are used and any thrown exceptions are <U>accumulated</U> and - * thrown as a single exception at the end of invoking all of them. - * - * @param <ARG> The argument type - * @param invokers The invokers to wrap - ignored if {@code null}/empty - * @return The wrapper - * @see #invokeAll(Object, Collection) invokeAll - */ - 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 = ExceptionUtils.accumulateException(err, t); - } - } - - if (err != null) { - throw err; - } - } - - /** - * Wraps a bunch of {@link Invoker}-s that return no value into one that invokes them in the same <U>order</U> as - * they appear. <B>Note:</B> stops when <U>first</U> invoker throws an exception (otherwise invokes all) - * - * @param <ARG> The argument type - * @param invokers The invokers to wrap - ignored if {@code null}/empty - * @return The wrapper - * @see #invokeTillFirstFailure(Object, Collection) invokeTillFirstFailure - */ - 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; - } -} diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java index ebc18c490..f96327397 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java @@ -33,6 +33,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.IntUnaryOperator; @@ -64,7 +65,6 @@ import org.apache.sshd.common.util.closeable.IoBaseCloseable; import org.apache.sshd.common.util.closeable.SimpleCloseable; import org.apache.sshd.common.util.functors.Int2IntFunction; import org.apache.sshd.common.util.io.IoUtils; -import org.apache.sshd.common.util.io.functors.Invoker; import org.apache.sshd.common.util.threads.CloseableExecutorService; import org.apache.sshd.common.util.threads.ExecutorServiceCarrier; import org.apache.sshd.core.CoreModuleProperties; @@ -130,7 +130,6 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements private CloseableExecutorService executor; private final List<RequestHandler<Channel>> requestHandlers = new CopyOnWriteArrayList<>(); - private final boolean isClient; private final CloseableLocalWindow localWindow; private final CloseableRemoteWindow remoteWindow; @@ -166,7 +165,6 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements gracefulFuture = new DefaultCloseFuture(discriminator, futureLock); localWindow = new CloseableLocalWindow(this, client); remoteWindow = new CloseableRemoteWindow(this, client); - isClient = client; channelListenerProxy = EventListenerUtils.proxyWrapper(ChannelListener.class, channelListeners); executor = executorService; addRequestHandlers(handlers); @@ -427,7 +425,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements Buffer b = new ByteArrayBuffer(4); b.putUInt(0); handleWindowAdjust(b); - } catch (IOException | ClassCastException e) { + } catch (IOException e) { getSession().exceptionCaught(e); } } else if (log.isDebugEnabled()) { @@ -439,10 +437,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements protected void signalChannelInitialized() throws IOException { try { - invokeChannelSignaller(l -> { - signalChannelInitialized(l); - return null; - }); + invokeChannelSignaller(l -> l.channelInitialized(this)); notifyStateChanged("init"); } catch (Throwable err) { @@ -459,33 +454,8 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements } } - protected void signalChannelInitialized(ChannelListener listener) { - if (listener == null) { - return; - } - - listener.channelInitialized(this); - } - protected void signalChannelOpenSuccess() { - try { - invokeChannelSignaller(l -> { - signalChannelOpenSuccess(l); - return null; - }); - } catch (Error | RuntimeException err) { - throw err; - } catch (Throwable err) { - throw new IllegalStateException(err); - } - } - - protected void signalChannelOpenSuccess(ChannelListener listener) { - if (listener == null) { - return; - } - - listener.channelOpenSuccess(this); + invokeChannelSignaller(l -> l.channelOpenSuccess(this)); } @Override @@ -510,10 +480,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements protected void signalChannelOpenFailure(Throwable reason) { try { - invokeChannelSignaller(l -> { - signalChannelOpenFailure(l, reason); - return null; - }); + invokeChannelSignaller(l -> l.channelOpenFailure(this, reason)); } catch (Throwable err) { Throwable ignored = ExceptionUtils.peelException(err); debug("signalChannelOpenFailure({}) failed ({}) to inform listener of open failure={}: {}", this, @@ -522,20 +489,9 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements } } - protected void signalChannelOpenFailure(ChannelListener listener, Throwable reason) { - if (listener == null) { - return; - } - - listener.channelOpenFailure(this, reason); - } - protected void notifyStateChanged(String hint) { try { - invokeChannelSignaller(l -> { - notifyStateChanged(l, hint); - return null; - }); + invokeChannelSignaller(l -> l.channelStateChanged(this, hint)); } catch (Throwable err) { Throwable e = ExceptionUtils.peelException(err); debug("notifyStateChanged({})[{}] {} while signal channel state change: {}", this, hint, @@ -547,14 +503,6 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements } } - protected void notifyStateChanged(ChannelListener listener, String hint) { - if (listener == null) { - return; - } - - listener.channelStateChanged(this, hint); - } - @Override public void addChannelListener(ChannelListener listener) { ChannelListener.validateListener(listener); @@ -800,10 +748,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements } } - invokeChannelSignaller(l -> { - signalChannelClosed(l, reason); - return null; - }); + invokeChannelSignaller(l -> l.channelClosed(this, reason)); } catch (Throwable err) { Throwable e = ExceptionUtils.peelException(err); debug("signalChannelClosed({}) {} while signal channel closed: {}", this, e.getClass().getSimpleName(), @@ -813,15 +758,7 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements } } - protected void signalChannelClosed(ChannelListener listener, Throwable reason) { - if (listener == null) { - return; - } - - listener.channelClosed(this, reason); - } - - protected void invokeChannelSignaller(Invoker<ChannelListener, Void> invoker) throws Throwable { + protected void invokeChannelSignaller(Consumer<ChannelListener> invoker) { Session session = getSession(); FactoryManager manager = (session == null) ? null : session.getFactoryManager(); ChannelListener[] listeners = { @@ -834,14 +771,14 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements continue; } try { - invoker.invoke(l); - } catch (Throwable t) { - err = ExceptionUtils.accumulateException(err, t); + invoker.accept(l); + } catch (RuntimeException e) { + err = ExceptionUtils.accumulateException(err, e); } } if (err != null) { - throw err; + ExceptionUtils.rethrowAsRuntimeException(err); } }