/* * 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 org.eclipse.sw360.datahandler.thrift.SW360Exception; import org.eclipse.sw360.datahandler.thrift.attachments.AttachmentContent; import org.eclipse.sw360.datahandler.thrift.components.FossologyStatus; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import static org.eclipse.sw360.datahandler.common.SW360Assert.assertNotEmpty; import static org.eclipse.sw360.datahandler.common.SW360Assert.fail; import static org.apache.log4j.Logger.getLogger; /** * @author daniele.fognini@tngtech.com */ @Component public class FossologyUploader { protected static final String FOSSOLOGY_COMMAND_UPLOAD = "./uploadFromSW360 -i '%s' -g '%s' -f '%s'"; protected static final String FOSSOLOGY_COMMAND_GET_STATUS = "./getStatusOfUpload -u '%d' -g '%s'"; protected static final String FOSSOLOGY_COMMAND_COPY_UPLOAD = "./duplicateUpload -u '%d' -g '%s'"; protected static final String COPY_STDIN_CMD = "cat > '%s'"; protected static final String CHMOD_EXEC_CMD = "chmod u+x '%s'"; private static final Logger log = getLogger(FossologyUploader.class); private final FossologySshConnector fossologySshConnector; @Autowired public FossologyUploader(FossologySshConnector fossologySshConnector) { this.fossologySshConnector = fossologySshConnector; } protected static int parseResultUploadId(String output) { final Pattern pattern = Pattern.compile("uploadId=(\\d*)"); final Matcher matcher = pattern.matcher(output); if (matcher.find()) { try { return Integer.parseInt(matcher.group(1)); } catch (Exception e) { log.error("fossology output parser caught an exception: " + e.getMessage(), e); } } log.error("cannot parse output from fossology uploader: '" + output + "'"); return -1; } private static String sanitizeQuotes(String string) { return string.replace("'", "_"); } public int uploadToFossology(InputStream inputStream, AttachmentContent attachment, String clearingTeam) { try { final CapturerOutputStream os = new CapturerOutputStream(); final String attachmentFilename = attachment.getFilename(); final String id = attachment.getId(); assertNotEmpty(id); assertNotEmpty(clearingTeam); assertNotEmpty(attachmentFilename); final String command = String.format(FOSSOLOGY_COMMAND_UPLOAD, sanitizeQuotes(id), sanitizeQuotes(clearingTeam), sanitizeQuotes(attachmentFilename)); final int exitCode = fossologySshConnector.runInFossologyViaSsh(command, inputStream, os); String output = os.getContent(); if (exitCode != 0) { log.error("upload to fossology failed: " + output); return -1; } return parseResultUploadId(output); } catch (SW360Exception e) { log.error("cannot upload file with id " + attachment.getId() + " (" + attachment.getFilename() + ") to fossology", e); return -1; } } public boolean duplicateInFossology(int uploadId, String clearingTeam) { String cmd = String.format(FOSSOLOGY_COMMAND_COPY_UPLOAD, uploadId, clearingTeam); CapturerOutputStream os = new CapturerOutputStream(); int i = fossologySshConnector.runInFossologyViaSsh(cmd, os); boolean success = i == 0; if (!success) { log.error("error duplicating Upload: " + os.getContent()); } return success; } public FossologyStatus getStatusInFossology(int uploadId, String clearingTeam) { try { final CapturerOutputStream os = new CapturerOutputStream(); if (uploadId < 0) { throw fail("bad Upload Id"); } assertNotEmpty(clearingTeam); final String command = String.format(FOSSOLOGY_COMMAND_GET_STATUS, uploadId, sanitizeQuotes(clearingTeam)); final int exitCode = fossologySshConnector.runInFossologyViaSsh(command, os); String output = os.getContent(); if (exitCode != 0) { log.error("get status in fossology failed: " + output); return FossologyStatus.CONNECTION_FAILED; } return parseResultStatus(output); } catch (SW360Exception e) { log.error("cannot check status of upload with id " + uploadId + " in fossology", e); return FossologyStatus.ERROR; } } protected FossologyStatus parseResultStatus(String output) { final Pattern pattern = Pattern.compile("status=(\\w*)"); final Matcher matcher = pattern.matcher(output); if (matcher.find()) { try { return FossologyStatus.valueOf(matcher.group(1)); } catch (Exception e) { log.error("fossology output parser caught exception: " + e.getMessage(), e); } } log.error("cannot parse output from fossology check status: '" + output + "'"); return FossologyStatus.CONNECTION_FAILED; } public boolean copyToFossology(String filename, InputStream content, boolean execBit) throws SW360Exception { final String quotedFileName = sanitizeQuotes(filename); String copyCmd = String.format(COPY_STDIN_CMD, quotedFileName); if (execBit) { copyCmd += " && " + String.format(CHMOD_EXEC_CMD, quotedFileName); } return fossologySshConnector.runInFossologyViaSsh(copyCmd, content) == 0; } protected static class CapturerOutputStream extends OutputStream { ByteArrayOutputStream os = new ByteArrayOutputStream(); @Override public void write(int b) throws IOException { os.write(b); } public String getContent() { return new String(os.toByteArray()); } } }