All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sshtools.client.tasks.AbstractSessionTask Maven / Gradle / Ivy

package com.sshtools.client.tasks;

/*-
 * #%L
 * Client API
 * %%
 * Copyright (C) 2002 - 2024 JADAPTIVE Limited
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.io.Closeable;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;

import com.sshtools.client.AbstractSessionChannel;
import com.sshtools.client.SshClient;
import com.sshtools.client.shell.ShellTimeoutException;
import com.sshtools.common.logger.Log;
import com.sshtools.common.ssh.ChannelRequestFuture;
import com.sshtools.common.ssh.SshConnection;
import com.sshtools.common.ssh.SshException;

/**
 * An abstract task for using the SSH session
 */
public abstract class AbstractSessionTask extends AbstractConnectionTask implements Closeable {

	/**
	 * Builder for {@link AbstractSessionTask}.
	 */
	protected static abstract class AbstractSessionTaskBuilder<
			B extends AbstractSessionTaskBuilder,
			SC extends AbstractSessionChannel,
			TT extends AbstractSessionTask> extends AbstractConnectionTaskBuilder { 

		private Optional> session = Optional.empty();
		private Optional future = Optional.empty();

		/**
		 * Set a function to create a custom session channel.
		 * 
		 * @param session session function
		 * @return builder for chaining
		 */
		public final AbstractSessionTaskBuilder withSession(Function session) {
			this.session = Optional.of(session);
			return this;
		}

		/**
		 * Set a custom {@link ChannelRequestFuture}.
		 * 
		 * @param future future
		 * @return builder for chaining
		 */
		public final AbstractSessionTaskBuilder withFuture(ChannelRequestFuture future) {
			this.future  = Optional.of(future);
			return this;
		}
	}
	
	private long timeout = 10000;
	private final ChannelRequestFuture future;
	
	/* TODO make final at 3.2.0 */
	private Optional session;
	
	public AbstractSessionTask(AbstractSessionTaskBuilder builder) {
		super(builder);
		session = builder.session.map(f -> f.apply(con));
		future = builder.future.orElseGet(() -> new ChannelRequestFuture());
	}

	@Deprecated
	public AbstractSessionTask(SshClient ssh, ChannelRequestFuture future) {
		super(ssh);
		this.future = future;
		this.session = Optional.empty();
	}

	@Deprecated
	public AbstractSessionTask(SshConnection con, ChannelRequestFuture future) {
		super(con);
		this.future = future;
		this.session = Optional.empty();
	}
	
	public AbstractSessionTask(SshConnection con) {
		this(con, new ChannelRequestFuture());
	}

	public T getSession() {
		if(session.isEmpty()) {
			session = Optional.of(createSession(con));
		}
		return session.get();
	}
	
	public void disconnect() {
		con.disconnect();
	}
	
	public ChannelRequestFuture getChannelFuture() {
		return future;
	}
	
	@Override
	public void doTask() {
		var session = getSession();
		
		con.openChannel(session);
		if(!session.getOpenFuture().waitFor(timeout).isSuccess()) {
			throw new IllegalStateException("Could not open session channel");
		}
		
		setupSession(session);
	

		try {
			if(Log.isDebugEnabled()) {
				Log.debug("Starting session task");
			}
			onOpenSession(session);
		} catch(Throwable ex) {
			this.lastError = ex;
		}
		
		closeOnTaskComplete();
	}
	
	@Deprecated(since = "3.1.0")
	protected void closeOnTaskComplete() {
		close();
	}
	
//		if(Log.isDebugEnabled()) {
//			Log.debug("Ending session task");
//		}
//		
//		session.close();
//		onCloseSession(session);
//		
//		done(Objects.isNull(lastError));
//		
//		if(Log.isDebugEnabled()) {
//			Log.debug("Session task is done success={}", String.valueOf(Objects.isNull(lastError)));
//		}
	
	protected abstract T createSession(SshConnection con);
	
	protected abstract void setupSession(T session);
	
	protected abstract void onOpenSession(T session) throws IOException, SshException, ShellTimeoutException;
	
	protected abstract void onCloseSession(T session);

	@Override
	public final void close() {
		if(Log.isDebugEnabled()) {
			Log.debug("Ending session task");
		}
		
		var session = getSession();
		session.close();
		onCloseSession(session);
		
		done(Objects.isNull(lastError));
		
		if(Log.isDebugEnabled()) {
			Log.debug("Session task is done success={}", String.valueOf(Objects.isNull(lastError)));
		}
	}

	public boolean isClosed() {
		return getSession().isClosed();
	}

	public void changeTerminalDimensions(int cols, int rows, int width, int height) {
		getSession().changeTerminalDimensions(cols, rows, width, height);
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy