/*
* Copyright Siemens AG, 2013-2015. Part of the SW360 Portal Project.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.sw360.fossology.ssh;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import org.eclipse.sw360.datahandler.thrift.SW360Exception;
import org.eclipse.sw360.fossology.config.FossologySettings;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static org.eclipse.sw360.datahandler.common.SW360Assert.fail;
import static java.lang.System.currentTimeMillis;
import static org.apache.log4j.Logger.getLogger;
/**
* @author daniele.fognini@tngtech.com
*/
@Component
public class FossologySshConnector {
private static final Logger log = getLogger(FossologySshConnector.class);
private static final OutputStream BLACK_HOLE = new OutputStream() {
@Override
public void write(int b) throws IOException {
}
};
private static final InputStream EMPTY_INPUT = new InputStream() {
@Override
public int read() throws IOException {
return -1;
}
};
private final JSchSessionProvider jSchSessionProvider;
private final int connectionTimeout;
private final long executionTimeout;
@Autowired
public FossologySshConnector(JSchSessionProvider jSchSessionProvider, FossologySettings fossologySettings) {
this.jSchSessionProvider = jSchSessionProvider;
executionTimeout = fossologySettings.getFossologyExecutionTimeout();
connectionTimeout = fossologySettings.getFossologyConnectionTimeout();
}
protected void waitCompletion(Channel channel, long timeout) throws SW360Exception {
long startTime = currentTimeMillis();
while (!channel.isClosed() && (currentTimeMillis() - startTime < timeout)) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw fail(e, "interrupted connection to Fossology");
}
}
if (!channel.isClosed()) {
throw fail("timeout while waiting for completion of connection to Fossology");
}
}
public int runInFossologyViaSsh(String command) {
return runInFossologyViaSsh(command, EMPTY_INPUT, BLACK_HOLE);
}
public int runInFossologyViaSsh(String command, InputStream stdin) {
return runInFossologyViaSsh(command, stdin, BLACK_HOLE);
}
public int runInFossologyViaSsh(String command, OutputStream stdout) {
return runInFossologyViaSsh(command, EMPTY_INPUT, stdout);
}
public int runInFossologyViaSsh(String command, InputStream stdin, OutputStream stdout) {
ChannelExec channel = null;
Session session = null;
int exitCode = -1;
try {
session = jSchSessionProvider.getSession(connectionTimeout);
channel = (ChannelExec) session.openChannel("exec");
channel.setOutputStream(stdout);
channel.setInputStream(stdin);
channel.setCommand(command);
channel.connect(connectionTimeout);
waitCompletion(channel, executionTimeout);
channel.disconnect();
exitCode = channel.getExitStatus();
} catch (JSchException | SW360Exception | NullPointerException | ClassCastException e) {
log.error("error executing remote command on Fossology Server " + jSchSessionProvider.getServerString(), e);
} finally {
if (channel != null && channel.isConnected()) {
channel.disconnect();
}
jSchSessionProvider.closeSession(session);
}
return exitCode;
}
}