blob: 34a1ba652ae3d9cd12c025e0481e356d2ff5054e [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2021 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.ide.core;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jsch.core.IJSchLocation;
import org.eclipse.jsch.core.IJSchService;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.eclipse.statet.jcommons.lang.Disposable;
import org.eclipse.statet.ecommons.net.ssh.core.ISshSessionService;
import org.eclipse.statet.base.core.StatetCore;
/**
* SSH session service implementation.
*
* Don't forget to dispose to close the open connections.
*/
public class SshSessionManager implements ISshSessionService, Disposable {
private static final int SSH_TIMEOUT= 60000;
private Map<String, Session> fPool;
public SshSessionManager() {
this.fPool= new HashMap<>();
}
@Override
public Session getSshSession(final String username, final String host, final int port,
final IProgressMonitor monitor) throws CoreException {
final String key= username + '@' + host + ':' + Integer.toString((port > 0) ? port : 22);
Session session= this.fPool.get(key);
try {
final IJSchService jschService= BaseCorePlugin.getInstance().getJSchService();
if (session == null) {
final IJSchLocation location= jschService.getLocation(username, host, port);
session= jschService.createSession(location, null);
}
if (!session.isConnected()) {
jschService.connect(session, SSH_TIMEOUT, new SubProgressMonitor(monitor, 1));
}
this.fPool.put(key, session);
return session;
}
catch (final JSchException e) {
// create new session, if existing session is broken
if ("Packet corrupt".equals(e.getMessage()) && this.fPool.values().remove(session)) { //$NON-NLS-1$
return getSshSession(username, host, port, monitor);
}
throw new CoreException(new Status(IStatus.ERROR, StatetCore.BUNDLE_ID, "Failed to create SSH connection", e));
}
}
@Override
public void dispose() {
final Collection<Session> sessions= this.fPool.values();
for (final Session session : sessions) {
session.disconnect();
}
this.fPool= null;
}
}