jenkins.plugins.coverity.CoverityLauncherDecorator Maven / Gradle / Ivy
The newest version!
/*******************************************************************************
* Copyright (c) 2011 Coverity, Inc
* 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
*
* Contributors:
* Coverity, Inc - initial implementation and documentation
*******************************************************************************/
package jenkins.plugins.coverity;
import com.coverity.ws.v5.CovRemoteServiceException_Exception;
import com.coverity.ws.v5.StreamDataObj;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.LauncherDecorator;
import hudson.Proc;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Executor;
import hudson.model.Node;
import hudson.model.Queue;
import hudson.model.TaskListener;
import hudson.remoting.Channel;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
/**
* This makes sure that all commands executed (when invocation assistance is enabled) are run through cov-build.
*/
@Extension
public class CoverityLauncherDecorator extends LauncherDecorator {
private static final Logger logger = Logger.getLogger(CoverityLauncherDecorator.class.getName());
/**
* A ThreadLocal that is used to disable cov-build when running other Coverity tools during the build.
*/
public static ThreadLocal SKIP = new ThreadLocal() {
@Override
protected Boolean initialValue() {
return false;
}
};
@Override
public Launcher decorate(Launcher launcher, Node node) {
Executor executor = Executor.currentExecutor();
if(executor == null) {
return launcher;
}
Queue.Executable exec = executor.getCurrentExecutable();
if(!(exec instanceof AbstractBuild)) {
return launcher;
}
AbstractBuild build = (AbstractBuild) exec;
AbstractProject project = build.getProject();
CoverityPublisher publisher = (CoverityPublisher) project.getPublishersList().get(CoverityPublisher.class);
if(publisher == null) {
return launcher;
}
InvocationAssistance ii = publisher.getInvocationAssistance();
if(ii == null) {
return launcher;
}
FilePath temp;
try {
if(ii.getIntermediateDir() == null) {
FilePath coverityDir = node.getRootPath().child("coverity");
coverityDir.mkdirs();
temp = coverityDir.createTempDir("temp-", null);
} else {
temp = new FilePath(node.getChannel(), ii.getIntermediateDir());
temp.mkdirs();
}
build.addAction(new CoverityTempDir(temp, ii.getIntermediateDir() == null));
} catch(IOException e) {
throw new RuntimeException("Error while creating temporary directory for Coverity", e);
} catch(InterruptedException e) {
throw new RuntimeException("Interrupted while creating temporary directory for Coverity");
}
// Do not run cov-build if language is "CSHARP"
boolean onlyCS = true;
for(CIMStream cs : publisher.getCimStreams()) {
CIMInstance cim = publisher.getDescriptor().getInstance(cs.getInstance());
String id = cs.getInstance() + "/" + cs.getStream();
try {
StreamDataObj stream = cim.getStream(cs.getStream());
if(stream == null) {
throw new RuntimeException("Could not find stream: " + id);
}
String language = stream.getLanguage();
if(!"CSHARP".equals(language)) {
onlyCS = false;
break;
}
} catch(CovRemoteServiceException_Exception e) {
throw new RuntimeException("Error while retrieving stream information for instance/stream: " + id, e);
} catch(IOException e) {
throw new RuntimeException("Error while retrieving stream information for instance/stream: " + id, e);
}
}
//look for old-style stream format
if(publisher.getCimInstance() != null) {
CIMInstance cim = publisher.getDescriptor().getInstance(publisher.getCimInstance());
String id = publisher.getCimInstance() + "/" + publisher.getStream();
try {
StreamDataObj stream = cim.getStream(publisher.getStream());
if(stream == null) {
throw new RuntimeException("Could not find stream: " + id);
}
String language = stream.getLanguage();
if(!"CSHARP".equals(language)) {
onlyCS = false;
}
} catch(CovRemoteServiceException_Exception e) {
throw new RuntimeException("Error while retrieving stream information for instance/stream: " + id, e);
} catch(IOException e) {
throw new RuntimeException("Error while retrieving stream information for instance/stream: " + id, e);
}
}
if(onlyCS) {
logger.info("Only streams of type CSHARP were found, skipping cov-build");
return launcher;
}
List args = new ArrayList();
args.add("cov-build-placeholder");
args.add("--dir");
args.add(temp.getRemote());
if(ii.getBuildArguments() != null) {
for(String arg : Util.tokenize(ii.getBuildArguments())) {
args.add(arg);
}
}
String blacklistTemp = ii.getCovBuildBlacklist();
String[] blacklist;
if(blacklistTemp != null) {
blacklist = blacklistTemp.split(",");
for(int i = 0; i < blacklist.length; i++) {
blacklist[i] = blacklist[i].trim();
}
} else {
blacklist = new String[0];
}
return new DecoratedLauncher(launcher, blacklist, node, args.toArray(new String[args.size()]));
}
/**
* A decorated {@link Launcher} that puts the given set of arguments as a prefix to any commands that it invokes.
*/
public class DecoratedLauncher extends Launcher {
private final Launcher decorated;
private final String[] prefix;
private final String[] blacklist;
private final String toolsDir;
private final Node node;
public DecoratedLauncher(Launcher decorated, String[] blacklist, Node node, String... prefix) {
super(decorated);
this.decorated = decorated;
this.prefix = prefix;
this.blacklist = blacklist;
this.node = node;
this.toolsDir = node.getRootPath().child("tools").getRemote();
}
private String[] getPrefix() {
String[] tp = prefix.clone();
tp[0] = getCovBuild();
return tp;
}
@Override
public Proc launch(ProcStarter starter) throws IOException {
if(!SKIP.get()) {
if(isBlacklisted(starter.cmds().get(0))) {
logger.info(starter.cmds().get(0) + " is blacklisted, skipping cov-build");
return decorated.launch(starter);
}
List cmds = starter.cmds();
//skip jdk installations
String lastArg = cmds.get(cmds.size() - 1);
if(lastArg.startsWith(toolsDir) && lastArg.endsWith(".sh")) {
logger.info(lastArg + " is a tools script, skipping cov-build");
return decorated.launch(starter);
}
cmds.addAll(0, Arrays.asList(getPrefix()));
starter.cmds(cmds);
boolean[] masks = starter.masks();
if(masks == null) {
masks = new boolean[cmds.size()];
starter.masks(masks);
} else {
starter.masks(prefix(masks));
}
}
return decorated.launch(starter);
}
@Override
public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map envVars) throws IOException, InterruptedException {
String lastArg = cmd[cmd.length - 1];
if(lastArg.startsWith(toolsDir) && lastArg.endsWith(".sh")) {
logger.info(lastArg + " is a tools script, skipping cov-build");
decorated.launchChannel(cmd, out, workDir, envVars);
}
return decorated.launchChannel(prefix(cmd), out, workDir, envVars);
}
/*
* When running remotely, overriding this method makes sure that the platform is detected correctly.
*/
@Override
public boolean isUnix() {
return decorated.isUnix();
}
@Override
public void kill(Map modelEnvVars) throws IOException, InterruptedException {
decorated.kill(modelEnvVars);
}
private String[] prefix(String[] args) {
if(isBlacklisted(args[0])) {
return args;
}
String[] newArgs = new String[args.length + prefix.length];
System.arraycopy(getPrefix(), 0, newArgs, 0, prefix.length);
System.arraycopy(args, 0, newArgs, prefix.length, args.length);
return newArgs;
}
private boolean[] prefix(boolean[] args) {
boolean[] newArgs = new boolean[args.length + prefix.length];
System.arraycopy(args, 0, newArgs, prefix.length, args.length);
return newArgs;
}
private boolean isBlacklisted(String cmd) {
for(String s : blacklist) {
if(s.equals(cmd)) {
return true;
}
}
return false;
}
private String getCovBuild() {
Executor executor = Executor.currentExecutor();
Queue.Executable exec = executor.getCurrentExecutable();
AbstractBuild build = (AbstractBuild) exec;
AbstractProject project = build.getProject();
CoverityPublisher publisher = (CoverityPublisher) project.getPublishersList().get(CoverityPublisher.class);
InvocationAssistance ii = publisher.getInvocationAssistance();
String covBuild = "cov-build";
TaskListener listener = decorated.getListener();
String home = null;
try {
home = publisher.getDescriptor().getHome(node, build.getEnvironment(listener));
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
}
if(ii.getSaOverride() != null) {
try {
home = new CoverityInstallation(ii.getSaOverride()).forEnvironment(build.getEnvironment(listener)).getHome();
} catch(IOException e) {
e.printStackTrace();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
if(home != null) {
covBuild = new FilePath(node.getChannel(), home).child("bin").child(covBuild).getRemote();
}
return covBuild;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy