/* * 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.agent.common; import java.io.IOException; import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; import org.apache.sshd.agent.SshAgentFactory; import org.apache.sshd.agent.SshAgentServer; import org.apache.sshd.common.FactoryManager; import org.apache.sshd.common.SshException; import org.apache.sshd.common.session.ConnectionService; import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.closeable.AbstractCloseable; /** * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a> */ public class DefaultAgentForwardSupport extends AbstractCloseable implements AgentForwardSupport { private final ConnectionService serviceInstance; private final AtomicReference<SshAgentServer> agentServerHolder = new AtomicReference<>(); public DefaultAgentForwardSupport(ConnectionService service) { serviceInstance = Objects.requireNonNull(service, "No connection service"); } @Override public String initialize() throws IOException { Session session = serviceInstance.getSession(); try { SshAgentServer agentServer; synchronized (agentServerHolder) { agentServer = agentServerHolder.get(); if (agentServer != null) { return agentServer.getId(); } agentServer = Objects.requireNonNull(createSshAgentServer(serviceInstance, session), "No agent server created"); agentServerHolder.set(agentServer); } String agentId = agentServer.getId(); if (log.isDebugEnabled()) { log.debug("initialize({}) id={}, server={}", session, agentId, agentServer); } return agentId; } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("initialize({}) failed ({}) to create server: {}", session, t.getClass().getSimpleName(), t.getMessage()); } if (log.isTraceEnabled()) { log.trace("initialize(" + session + ") server creation failure details", t); } if (t instanceof IOException) { throw (IOException) t; } else { throw new SshException(t); } } } protected SshAgentServer createSshAgentServer(ConnectionService service, Session session) throws Throwable { FactoryManager manager = Objects.requireNonNull(session.getFactoryManager(), "No session factory manager"); SshAgentFactory factory = Objects.requireNonNull(manager.getAgentFactory(), "No agent factory"); return factory.createServer(service); } @Override public void close() throws IOException { SshAgentServer agentServer = agentServerHolder.getAndSet(null); if (agentServer != null) { if (log.isDebugEnabled()) { log.debug("close({}) closing server={}", serviceInstance.getSession(), agentServer); } agentServer.close(); } } @Override protected void doCloseImmediately() { try { close(); } catch (IOException e) { throw new RuntimeException("Failed (" + e.getClass().getSimpleName() + ") to close agent: " + e.getMessage(), e); } super.doCloseImmediately(); } @Override public String toString() { return getClass().getSimpleName() + "[" + serviceInstance.getSession() + "]"; } }