Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/SynopsysCoverityCredentialsHelper.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Optional;

import org.jenkinsci.plugins.plaincredentials.FileCredentials;

import com.cloudbees.plugins.credentials.CredentialsMatcher;
import com.cloudbees.plugins.credentials.CredentialsMatchers;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl;
import com.synopsys.integration.coverity.authentication.AuthenticationKeyFile;
import com.synopsys.integration.coverity.authentication.AuthenticationKeyFileUtility;
import com.synopsys.integration.jenkins.wrapper.JenkinsWrapper;
import com.synopsys.integration.jenkins.wrapper.SynopsysCredentialsHelper;
import com.synopsys.integration.log.IntLogger;
import com.synopsys.integration.log.SilentIntLogger;
import com.synopsys.integration.rest.credentials.CredentialsBuilder;

import hudson.security.ACL;
import hudson.util.ListBoxModel;
import hudson.util.Secret;
import jenkins.model.Jenkins;

public class SynopsysCoverityCredentialsHelper extends SynopsysCredentialsHelper {
    public static final Class<FileCredentials> AUTH_KEY_FILE_CREDENTIALS_CLASS = FileCredentials.class;
    public static final CredentialsMatcher AUTH_KEY_FILE_CREDENTIALS = CredentialsMatchers.instanceOf(AUTH_KEY_FILE_CREDENTIALS_CLASS);
    public static final CredentialsMatcher SUPPORTED_CREDENTIALS_TYPES = CredentialsMatchers.anyOf(AUTH_KEY_FILE_CREDENTIALS, CredentialsMatchers.instanceOf(USERNAME_PASSWORD_CREDENTIALS_CLASS));
    private final IntLogger logger;
    private final JenkinsWrapper jenkinsWrapper;

    public SynopsysCoverityCredentialsHelper(IntLogger logger, JenkinsWrapper jenkinsWrapper) {
        super(jenkinsWrapper);
        this.jenkinsWrapper = jenkinsWrapper;
        this.logger = logger;
    }

    public static SynopsysCoverityCredentialsHelper silentHelper(JenkinsWrapper jenkinsWrapper) {
        return new SynopsysCoverityCredentialsHelper(new SilentIntLogger(), jenkinsWrapper);
    }

    public ListBoxModel listSupportedCredentials() {
        Optional<Jenkins> optionalJenkins = jenkinsWrapper.getJenkins();
        if (optionalJenkins.isPresent()) {
            Jenkins jenkins = optionalJenkins.get();
            return new StandardListBoxModel()
                       .includeEmptyValue()
                       .includeMatchingAs(ACL.SYSTEM, jenkins, StandardCredentials.class, Collections.emptyList(), SUPPORTED_CREDENTIALS_TYPES);
        } else {
            return new StandardListBoxModel()
                .includeEmptyValue();
        }
    }

    public Optional<FileCredentials> getAuthenticationKeyFileCredentialsById(String credentialsId) {
        return getCredentialsById(AUTH_KEY_FILE_CREDENTIALS_CLASS, credentialsId);
    }

    public Optional<String> getCoverityUsernameById(String credentialsId) {
        return getIntegrationCredentialsById(credentialsId)
                   .getUsername();
    }

    public Optional<String> getCoverityPassphraseById(String credentialsId) {
        return getUsernamePasswordCredentialsById(credentialsId)
                   .map(UsernamePasswordCredentialsImpl::getPassword)
                   .map(Secret::getPlainText);
    }

    @Override
    public com.synopsys.integration.rest.credentials.Credentials getIntegrationCredentialsById(String credentialsId) {
        Optional<UsernamePasswordCredentialsImpl> possibleUsernamePasswordCredentials = getUsernamePasswordCredentialsById(credentialsId);
        Optional<FileCredentials> possibleAuthKeyCredentials = getAuthenticationKeyFileCredentialsById(credentialsId);
        CredentialsBuilder credentialsBuilder = com.synopsys.integration.rest.credentials.Credentials.newBuilder();

        if (possibleUsernamePasswordCredentials.isPresent()) {
            UsernamePasswordCredentialsImpl usernamePasswordCredentials = possibleUsernamePasswordCredentials.get();

            credentialsBuilder.setUsernameAndPassword(usernamePasswordCredentials.getUsername(), usernamePasswordCredentials.getPassword().getPlainText());
        }

        if (possibleAuthKeyCredentials.isPresent()) {
            FileCredentials fileCredentials = possibleAuthKeyCredentials.get();
            AuthenticationKeyFileUtility authenticationKeyFileUtility = AuthenticationKeyFileUtility.defaultUtility();

            try (InputStream keyFileInputStream = fileCredentials.getContent()) {
                AuthenticationKeyFile authenticationKeyFile = authenticationKeyFileUtility.readAuthenticationKeyFile(keyFileInputStream);

                credentialsBuilder.setUsernameAndPassword(authenticationKeyFile.username, authenticationKeyFile.key);
            } catch (IOException e) {
                logger.trace("Could not parse authentication key file with credentials id " + credentialsId + " because: ", e);
            }

        }

        return credentialsBuilder.build();
    }

}

## 内容2
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/extensions/CheckForIssuesInView.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity.extensions;

import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.slf4j.LoggerFactory;

import com.synopsys.integration.jenkins.annotations.HelpMarkdown;
import com.synopsys.integration.jenkins.coverity.extensions.buildstep.CoverityBuildStep;
import com.synopsys.integration.jenkins.coverity.extensions.utils.IssueViewFieldHelper;
import com.synopsys.integration.jenkins.extensions.JenkinsSelectBoxEnum;
import com.synopsys.integration.log.Slf4jIntLogger;

import hudson.Extension;
import hudson.RelativePath;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.ListBoxModel;

public class CheckForIssuesInView extends AbstractDescribableImpl<CheckForIssuesInView> {
    // Jenkins directly serializes the names of the fields, so they are an important part of the plugin's API.
    // Be aware by changing a field name, you will also need to change these strings and will likely break previous implementations.
    // Jenkins Common provides convenient access to the XSTREAM instance that Jenkins uses to serialize the classes, you can use the serialization methods on that class to rename fields without breaking them.
    // --rotte MAY 2021
    public static final String FIELD_VIEW_NAME = "viewName";
    public static final String FIELD_BUILD_STATUS_FOR_ISSUES = "buildStatusForIssues";
    public static final String PATH_TO_COVERITY_BUILD_STEP = "..";

    @HelpMarkdown("Specify the name of the Coverity view that you would like to check for issues.  \r\n"
                      + "The resulting view name is stored in the $COV_VIEW environment variable, and affects checking for issues in both the full and incremental analysis, if configured.")
    private final String viewName;
    @HelpMarkdown("Specify the build status to set if issues are found in the configured view.")
    private final BuildStatus buildStatusForIssues;

    @DataBoundConstructor
    public CheckForIssuesInView(String viewName, String buildStatusForIssues) {
        this.viewName = viewName;
        this.buildStatusForIssues = BuildStatus.valueOf(buildStatusForIssues);
    }

    public BuildStatus getBuildStatusForIssues() {
        return buildStatusForIssues;
    }

    public String getViewName() {
        return viewName;
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    @Extension
    public static class DescriptorImpl extends Descriptor<CheckForIssuesInView> {
        private final IssueViewFieldHelper issueViewFieldHelper;

        public DescriptorImpl() {
            super(CheckForIssuesInView.class);
            load();
            Slf4jIntLogger slf4jIntLogger = new Slf4jIntLogger(LoggerFactory.getLogger(CheckForIssuesInView.class));
            issueViewFieldHelper = new IssueViewFieldHelper(slf4jIntLogger);
        }

        public ListBoxModel doFillViewNameItems(
            @RelativePath(PATH_TO_COVERITY_BUILD_STEP) @QueryParameter(CoverityBuildStep.FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @RelativePath(PATH_TO_COVERITY_BUILD_STEP) @QueryParameter(CoverityBuildStep.FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials,
            @RelativePath(PATH_TO_COVERITY_BUILD_STEP) @QueryParameter(CoverityBuildStep.FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter("updateNow") boolean updateNow
        ) throws InterruptedException {
            if (updateNow) {
                issueViewFieldHelper.updateNow(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
            }
            return issueViewFieldHelper.getViewNamesForListBox(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
        }

        public ListBoxModel doFillBuildStatusForIssuesItems() {
            return JenkinsSelectBoxEnum.toListBoxModel(BuildStatus.values());
        }

    }

}

## 内容3
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/extensions/buildstep/CoverityBuildStep.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity.extensions.buildstep;

import java.io.IOException;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.lang.StringUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.slf4j.LoggerFactory;

import com.synopsys.integration.jenkins.annotations.HelpMarkdown;
import com.synopsys.integration.jenkins.coverity.SynopsysCoverityCredentialsHelper;
import com.synopsys.integration.jenkins.coverity.extensions.CheckForIssuesInView;
import com.synopsys.integration.jenkins.coverity.extensions.CleanUpAction;
import com.synopsys.integration.jenkins.coverity.extensions.ConfigureChangeSetPatterns;
import com.synopsys.integration.jenkins.coverity.extensions.OnCommandFailure;
import com.synopsys.integration.jenkins.coverity.extensions.global.CoverityConnectInstance;
import com.synopsys.integration.jenkins.coverity.extensions.utils.CoverityConnectionFieldHelper;
import com.synopsys.integration.jenkins.coverity.extensions.utils.ProjectStreamFieldHelper;
import com.synopsys.integration.jenkins.coverity.stepworkflow.CoverityWorkflowStepFactory;
import com.synopsys.integration.jenkins.extensions.JenkinsIntLogger;
import com.synopsys.integration.jenkins.extensions.JenkinsSelectBoxEnum;
import com.synopsys.integration.jenkins.wrapper.JenkinsVersionHelper;
import com.synopsys.integration.jenkins.wrapper.JenkinsWrapper;
import com.synopsys.integration.log.Slf4jIntLogger;

import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Builder;
import hudson.util.ComboBoxModel;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;

public class CoverityBuildStep extends Builder {
    // Jenkins directly serializes the names of the fields, so they are an important part of the plugin's API.
    public static final String FIELD_COVERITY_INSTANCE_URL = "coverityInstanceUrl";
    public static final String FIELD_PROJECT_NAME = "projectName";
    public static final String FIELD_STREAM_NAME = "streamName";
    public static final String NESTED_DESCRIPTOR_CHECK_FOR_ISSUES = "checkForIssuesInView";
    public static final String NESTED_DESCRIPTOR_CONFIGURE_CHANGE_SET_PATTERNS = "configureChangeSetPatterns";
    public static final String NESTED_DESCRIPTOR_COVERITY_RUN_CONFIGURATION = "coverityRunConfiguration";
    public static final String FIELD_ON_COMMAND_FAILURE = "onCommandFailure";
    public static final String FIELD_CLEAN_UP_ACTION = "cleanUpAction";
    public static final String FIELD_OVERRIDE_CREDENTIALS = "overrideDefaultCredentials";
    public static final String FIELD_CREDENTIALS_ID = "credentialsId";

    @HelpMarkdown("Specify which Synopsys Coverity connect instance to run this job against.  \r\n"
                      + "The resulting Synopsys Coverity connect instance URL is stored in the $COV_URL environment variable, and will affect both the full and incremental analysis.")
    private final String coverityInstanceUrl;

    @HelpMarkdown("Specify the name of the Coverity project.  \r\n"
                      + "The resulting project name is stored in the $COV_PROJECT environment variable, and will affect both the full and incremental analysis.")
    private final String projectName;

    @HelpMarkdown("Specify the name of the Coverity stream that you would like to use for the commands.  \r\n"
                      + "The resulting stream name is stored in the $COV_STREAM environment variable, and will affect both the full and incremental analysis.")
    private final String streamName;

    private final CheckForIssuesInView checkForIssuesInView;

    private final ConfigureChangeSetPatterns configureChangeSetPatterns;

    private final CoverityRunConfiguration coverityRunConfiguration;

    @HelpMarkdown("Specify the action to take if a Coverity static analysis command fails.")
    private final OnCommandFailure onCommandFailure;

    // Any field set by a DataBoundSetter should be explicitly declared as @Nullable to avoid accidental NPEs -- rotte 10/21/2019
    @Nullable
    @HelpMarkdown("Specify the clean up action to perform on a successful execution.  \r\n"
                      + "Will either persist or delete the intermediate directory created by the specified capture type.")
    private CleanUpAction cleanUpAction;

    @Nullable
    @HelpMarkdown("Specify the credentials to use with the Synopsys Coverity connect instance.")
    private String credentialsId;

    @Nullable
    private Boolean overrideDefaultCredentials;

    @DataBoundConstructor
    public CoverityBuildStep(String coverityInstanceUrl, String onCommandFailure, String projectName, String streamName, CheckForIssuesInView checkForIssuesInView,
        ConfigureChangeSetPatterns configureChangeSetPatterns, CoverityRunConfiguration coverityRunConfiguration) {
        this.coverityInstanceUrl = coverityInstanceUrl;
        this.projectName = projectName;
        this.streamName = streamName;
        this.checkForIssuesInView = checkForIssuesInView;
        this.configureChangeSetPatterns = configureChangeSetPatterns;
        this.coverityRunConfiguration = coverityRunConfiguration;
        this.onCommandFailure = OnCommandFailure.valueOf(onCommandFailure);
    }

    public CleanUpAction getCleanUpAction() {
        return cleanUpAction;
    }

    @DataBoundSetter
    public void setCleanUpAction(CleanUpAction cleanUpAction) {
        this.cleanUpAction = cleanUpAction;
    }

    public String getCredentialsId() {
        return credentialsId;
    }

    @DataBoundSetter
    public void setCredentialsId(String credentialsId) {
        this.credentialsId = credentialsId;
    }

    public Boolean getOverrideDefaultCredentials() {
        return overrideDefaultCredentials;
    }

    @DataBoundSetter
    public void setOverrideDefaultCredentials(Boolean overrideDefaultCredentials) {
        this.overrideDefaultCredentials = overrideDefaultCredentials;
    }

    public String getCoverityInstanceUrl() {
        return coverityInstanceUrl;
    }

    public OnCommandFailure getOnCommandFailure() {
        return onCommandFailure;
    }

    public ConfigureChangeSetPatterns getConfigureChangeSetPatterns() {
        return configureChangeSetPatterns;
    }

    public CheckForIssuesInView getCheckForIssuesInView() {
        return checkForIssuesInView;
    }

    public String getProjectName() {
        return projectName;
    }

    public String getStreamName() {
        return streamName;
    }

    public CoverityRunConfiguration getCoverityRunConfiguration() {
        return coverityRunConfiguration;
    }

    @Override
    public BuildStepMonitor getRequiredMonitorService() {
        return BuildStepMonitor.NONE;
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    @Override
    public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
        String remoteWorkingDirectoryPath = computeRemoteWorkingDirectory(coverityRunConfiguration, build.getWorkspace(), build.getProject());

        CoverityWorkflowStepFactory coverityWorkflowStepFactory = new CoverityWorkflowStepFactory(build.getEnvironment(listener), build.getBuiltOn(), launcher, listener);
        JenkinsIntLogger logger = coverityWorkflowStepFactory.getOrCreateLogger();
        JenkinsVersionHelper jenkinsVersionHelper = JenkinsWrapper.initializeFromJenkinsJVM().getVersionHelper();

        String resolvedCredentialsId;
        if (Boolean.TRUE.equals(overrideDefaultCredentials)) {
            resolvedCredentialsId = credentialsId;
        } else {
            CoverityConnectInstance coverityConnectInstance = coverityWorkflowStepFactory.getCoverityConnectInstanceFromUrl(coverityInstanceUrl);
            resolvedCredentialsId = coverityConnectInstance.getDefaultCredentialsId();
        }

        CoverityBuildStepWorkflow coverityBuildStepWorkflow = new CoverityBuildStepWorkflow(
            logger,
            jenkinsVersionHelper,
            () -> coverityWorkflowStepFactory.getWebServiceFactoryFromUrl(coverityInstanceUrl, resolvedCredentialsId),
            coverityWorkflowStepFactory,
            build,
            remoteWorkingDirectoryPath,
            coverityInstanceUrl,
            resolvedCredentialsId,
            projectName,
            streamName,
            coverityRunConfiguration,
            configureChangeSetPatterns,
            checkForIssuesInView,
            onCommandFailure,
            cleanUpAction
        );

        return coverityBuildStepWorkflow.perform();
    }

    private String computeRemoteWorkingDirectory(CoverityRunConfiguration coverityRunConfiguration, FilePath buildWorkspace, AbstractProject<?, ?> project) {
        boolean isDefaultCoverityWorkflow = CoverityRunConfiguration.RunConfigurationType.SIMPLE.equals(coverityRunConfiguration.getRunConFigurationType());
        String customWorkingDirectory = isDefaultCoverityWorkflow ? ((SimpleCoverityRunConfiguration) coverityRunConfiguration).getCustomWorkingDirectory() : null;

        if (StringUtils.isNotBlank(customWorkingDirectory)) {
            return customWorkingDirectory;
        } else if (buildWorkspace != null) {
            return buildWorkspace.getRemote();
        } else {
            return project.getCustomWorkspace();
        }
    }

    @Extension
    public static class DescriptorImpl extends BuildStepDescriptor<Builder> {
        private final CoverityConnectionFieldHelper coverityConnectionFieldHelper;
        private final ProjectStreamFieldHelper projectStreamFieldHelper;
        private final SynopsysCoverityCredentialsHelper credentialsHelper;

        public DescriptorImpl() {
            super(CoverityBuildStep.class);
            load();

            Slf4jIntLogger slf4jIntLogger = new Slf4jIntLogger(LoggerFactory.getLogger(this.getClass()));
            coverityConnectionFieldHelper = new CoverityConnectionFieldHelper(slf4jIntLogger);
            projectStreamFieldHelper = new ProjectStreamFieldHelper(slf4jIntLogger);
            credentialsHelper = new SynopsysCoverityCredentialsHelper(slf4jIntLogger, JenkinsWrapper.initializeFromJenkinsJVM());
        }

        @Override
        @Nonnull
        public String getDisplayName() {
            return "Execute Synopsys Coverity static analysis";
        }

        @Override
        public boolean isApplicable(Class<? extends AbstractProject> jobType) {
            return true;
        }

        public ListBoxModel doFillCoverityInstanceUrlItems() {
            return coverityConnectionFieldHelper.doFillCoverityInstanceUrlItems();
        }

        public ListBoxModel doFillCredentialsIdItems() {
            return credentialsHelper.listSupportedCredentials();
        }

        public FormValidation doCheckCoverityInstanceUrl(@QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl, @QueryParameter(FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials, @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrl(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
        }

        public ComboBoxModel doFillProjectNameItems(@QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl, @QueryParameter(FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials, @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId, @QueryParameter("updateNow") boolean updateNow) throws InterruptedException {
            if (updateNow) {
                projectStreamFieldHelper.updateNow(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
            }
            return projectStreamFieldHelper.getProjectNamesForComboBox(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
        }

        public FormValidation doCheckProjectName(@QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl, @QueryParameter(FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials, @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId, @QueryParameter(FIELD_PROJECT_NAME) String projectName) {
            FormValidation urlValidation = coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
            if (urlValidation.kind == FormValidation.Kind.ERROR) {
                return urlValidation;
            } else {
                return projectStreamFieldHelper.checkForProjectInCache(coverityInstanceUrl, overrideDefaultCredentials, credentialsId, projectName);
            }
        }

        public ComboBoxModel doFillStreamNameItems(@QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl, @QueryParameter(FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials, @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId, @QueryParameter(FIELD_PROJECT_NAME) String projectName) throws InterruptedException {
            return projectStreamFieldHelper.getStreamNamesForComboBox(coverityInstanceUrl, overrideDefaultCredentials,credentialsId, projectName);
        }

        public FormValidation doCheckStreamName(@QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl, @QueryParameter(FIELD_OVERRIDE_CREDENTIALS) Boolean overrideDefaultCredentials, @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId, @QueryParameter(FIELD_PROJECT_NAME) String projectName, @QueryParameter(FIELD_STREAM_NAME) String streamName) {
            FormValidation urlValidation = coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, overrideDefaultCredentials, credentialsId);
            if (urlValidation.kind == FormValidation.Kind.ERROR) {
                return urlValidation;
            } else {
                return projectStreamFieldHelper.checkForStreamInCache(coverityInstanceUrl, overrideDefaultCredentials, credentialsId, projectName, streamName);
            }
        }

        public ListBoxModel doFillOnCommandFailureItems() {
            return JenkinsSelectBoxEnum.toListBoxModel(OnCommandFailure.values());
        }

        public ListBoxModel doFillCleanUpActionItems() {
            return JenkinsSelectBoxEnum.toListBoxModel(CleanUpAction.values());
        }

        public CoverityRunConfiguration getDefaultCoverityRunConfiguration() {
            return SimpleCoverityRunConfiguration.DEFAULT_CONFIGURATION();
        }

    }

}

## 内容4
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/extensions/global/CoverityConnectInstance.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity.extensions.global;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Optional;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.jenkinsci.plugins.plaincredentials.FileCredentials;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.verb.POST;
import org.slf4j.LoggerFactory;

import com.synopsys.integration.coverity.config.CoverityServerConfig;
import com.synopsys.integration.jenkins.annotations.HelpMarkdown;
import com.synopsys.integration.jenkins.coverity.SynopsysCoverityCredentialsHelper;
import com.synopsys.integration.jenkins.coverity.exception.CoverityJenkinsAbortException;
import com.synopsys.integration.jenkins.coverity.extensions.utils.CoverityConnectionFieldHelper;
import com.synopsys.integration.jenkins.wrapper.JenkinsWrapper;
import com.synopsys.integration.log.IntLogger;
import com.synopsys.integration.log.Slf4jIntLogger;
import com.synopsys.integration.rest.credentials.Credentials;

import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;

public class CoverityConnectInstance extends AbstractDescribableImpl<CoverityConnectInstance> {
    @HelpMarkdown("Specify the URL for your Coverity Connect instance.  \r\n"
                      + "Populates the $COV_HOST and $COV_PORT environment variables")
    private final String url;

    @HelpMarkdown("Specify the default credentials or authentication key file for authenticating with your Coverity Connect instance. Credentials can be specified on a per-execution basis in the Freestyle or Pipeline job config.  \r\n"
                      + "The credentials specified here will be used if no other credentials are provided in the job config.  \r\n"
                      + "**Note:** \"Username with password\" and \"Secret File\" are the only kind of credentials supported.")
    private final String defaultCredentialsId;

    // A backwards-compatibility field for defaultCredentialsId.
    // Ideally we could find a way to remove this and use XSTREAM aliasing instead, but previous attempts have not been successful.
    // --rotte JUN 2021
    private transient String credentialId;

    @DataBoundConstructor
    public CoverityConnectInstance(String url, String defaultCredentialsId) {
        this.url = url;
        this.defaultCredentialsId = defaultCredentialsId;
    }

    @DataBoundSetter
    public void setCredentialId(String credentialId){
        this.credentialId = credentialId;
    }

    public String getDefaultCredentialsId() {
        if (credentialId != null) {
            return credentialId;
        }
        return defaultCredentialsId;
    }

    public String getUrl() {
        return url;
    }

    public Optional<URL> getCoverityURL() {
        URL coverityUrl = null;
        if (url != null) {
            try {
                coverityUrl = new URL(url);
            } catch (MalformedURLException ignored) {
                // Handled by form validation in the global configuration
            }
        }

        return Optional.ofNullable(coverityUrl);
    }

    public CoverityServerConfig getCoverityServerConfig(IntLogger logger, String credentialsId) throws IllegalArgumentException, IllegalStateException {
        return CoverityServerConfig.newBuilder()
                   .setUrl(url)
                   .setCredentials(getCoverityServerCredentials(logger, credentialsId))
                   .build();
    }

    public Credentials getCoverityServerCredentials(IntLogger logger, String credentialId) {
        SynopsysCoverityCredentialsHelper synopsysCoverityCredentialsHelper = new SynopsysCoverityCredentialsHelper(logger, JenkinsWrapper.initializeFromJenkinsJVM());
        return synopsysCoverityCredentialsHelper.getIntegrationCredentialsById(credentialId);
    }

    public Optional<String> getUsername(IntLogger logger, String credentialId) {
        SynopsysCoverityCredentialsHelper synopsysCoverityCredentialsHelper = new SynopsysCoverityCredentialsHelper(logger,JenkinsWrapper.initializeFromJenkinsJVM());
        return synopsysCoverityCredentialsHelper.getCoverityUsernameById(credentialId);
    }

    public Optional<String> getPassphrase(String credentialId) {
        SynopsysCoverityCredentialsHelper synopsysCoverityCredentialsHelper = SynopsysCoverityCredentialsHelper.silentHelper(JenkinsWrapper.initializeFromJenkinsJVM());
        return synopsysCoverityCredentialsHelper.getCoverityPassphraseById(credentialId);
    }

    public Optional<String> getAuthenticationKeyFileContents(IntLogger logger, String credentialId) throws CoverityJenkinsAbortException {
        SynopsysCoverityCredentialsHelper synopsysCoverityCredentialsHelper = new SynopsysCoverityCredentialsHelper(logger, JenkinsWrapper.initializeFromJenkinsJVM());
        Optional<FileCredentials> authenticationKeyFileCredentials = synopsysCoverityCredentialsHelper.getAuthenticationKeyFileCredentialsById(credentialId);
        String contents = null;

        if (authenticationKeyFileCredentials.isPresent()) {
            try (InputStream inputStream = authenticationKeyFileCredentials.get().getContent()) {
                contents = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
            } catch (IOException e) {
                throw new CoverityJenkinsAbortException("Authentication Key File could not be read from the Synopsys Coverity for Jenkins global configuration.");
            }
        }

        return Optional.ofNullable(contents);
    }

    public boolean isEmpty() {
        return null == url && null == defaultCredentialsId;
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    @Extension
    public static class DescriptorImpl extends Descriptor<CoverityConnectInstance> {
        private final CoverityConnectionFieldHelper coverityConnectionFieldHelper;
        private final SynopsysCoverityCredentialsHelper credentialsHelper;

        public DescriptorImpl() {
            super(CoverityConnectInstance.class);
            load();
            Slf4jIntLogger slf4jIntLogger = new Slf4jIntLogger(LoggerFactory.getLogger(this.getClass()));
            coverityConnectionFieldHelper = new CoverityConnectionFieldHelper(slf4jIntLogger);
            credentialsHelper = new SynopsysCoverityCredentialsHelper(slf4jIntLogger, JenkinsWrapper.initializeFromJenkinsJVM());
        }

        public FormValidation doCheckUrl(@QueryParameter("url") String url) {
            JenkinsWrapper.initializeFromJenkinsJVM().getJenkins().ifPresent(jenkins -> jenkins.checkPermission(Jenkins.ADMINISTER));
            if (StringUtils.isBlank(url)) {
                return FormValidation.error("Please provide a URL for the Coverity Connect instance.");
            }
            try {
                new URL(url);
            } catch (MalformedURLException e) {
                return FormValidation.error(e, String.format("The provided URL for the Coverity Connect instance is not a valid URL. Error: %s", e.getMessage()));
            }
            return FormValidation.ok();
        }

        public ListBoxModel doFillDefaultCredentialsIdItems() {
            return credentialsHelper.listSupportedCredentials();
        }

        @POST
        public FormValidation doTestConnection(@QueryParameter("url") String url, @QueryParameter("defaultCredentialsId") String defaultCredentialsId) {
            JenkinsWrapper.initializeFromJenkinsJVM().getJenkins().ifPresent(jenkins -> jenkins.checkPermission(Jenkins.ADMINISTER));
            FormValidation urlValidation = doCheckUrl(url);
            if (!FormValidation.Kind.OK.equals(urlValidation.kind)) {
                return urlValidation;
            }

            if (StringUtils.isBlank(defaultCredentialsId)) {
                return FormValidation.error("Please specify the credentials for the Coverity Connect instance.");
            }

            CoverityConnectInstance coverityConnectInstance = new CoverityConnectInstance(url, defaultCredentialsId);
            return coverityConnectionFieldHelper.testConnectionToCoverityInstance(coverityConnectInstance, defaultCredentialsId);
        }
    }

}

## 内容5
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/extensions/pipeline/CheckForIssuesStep.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity.extensions.pipeline;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.UnaryOperator;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.jenkinsci.Symbol;
import org.jenkinsci.plugins.workflow.graph.FlowNode;
import org.jenkinsci.plugins.workflow.steps.Step;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import org.jenkinsci.plugins.workflow.steps.StepExecution;
import org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.slf4j.LoggerFactory;

import com.synopsys.integration.jenkins.annotations.HelpMarkdown;
import com.synopsys.integration.jenkins.coverity.CoverityJenkinsIntLogger;
import com.synopsys.integration.jenkins.coverity.JenkinsCoverityEnvironmentVariable;
import com.synopsys.integration.jenkins.coverity.SynopsysCoverityCredentialsHelper;
import com.synopsys.integration.jenkins.coverity.extensions.global.CoverityConnectInstance;
import com.synopsys.integration.jenkins.coverity.extensions.utils.CoverityConnectionFieldHelper;
import com.synopsys.integration.jenkins.coverity.extensions.utils.IssueViewFieldHelper;
import com.synopsys.integration.jenkins.coverity.extensions.utils.ProjectStreamFieldHelper;
import com.synopsys.integration.jenkins.coverity.stepworkflow.CoverityWorkflowStepFactory;
import com.synopsys.integration.jenkins.wrapper.JenkinsVersionHelper;
import com.synopsys.integration.jenkins.wrapper.JenkinsWrapper;
import com.synopsys.integration.log.Slf4jIntLogger;
import com.synopsys.integration.util.IntEnvironmentVariables;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.Launcher;
import hudson.Util;
import hudson.model.Node;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;

public class CheckForIssuesStep extends Step implements Serializable {
    public static final String DISPLAY_NAME = "Check for Issues in Coverity View";
    public static final String PIPELINE_NAME = "coverityIssueCheck";
    private static final long serialVersionUID = 3602102048550370960L;

    // Jenkins directly serializes the names of the fields, so they are an important part of the plugin's API.
    // Be aware by changing a field name, you will also need to change these strings and will likely break previous implementations.
    // Jenkins Common provides convenient access to the XSTREAM instance that Jenkins uses to serialize the classes, you can use the serialization methods on that class to rename fields without breaking them.
    // --rotte MAY 2021
    public static final String FIELD_COVERITY_INSTANCE_URL = "coverityInstanceUrl";
    public static final String FIELD_PROJECT_NAME = "projectName";
    public static final String FIELD_STREAM_NAME = "streamName";
    public static final String FIELD_VIEW_NAME = "viewName";
    public static final String FIELD_CREDENTIALS_ID = "credentialsId";
    public static final String FIELD_RETURN_ISSUE_COUNT = "returnIssueCount";
    public static final String FIELD_MARK_UNSTABLE = "markUnstable";

    // Any field set by a DataBoundSetter should be explicitly declared as nullable to avoid NPEs
    @Nullable
    @HelpMarkdown("Specify which Synopsys Coverity connect instance to check for issues.")
    private String coverityInstanceUrl;

    @Nullable
    @HelpMarkdown("Specify the credentials to use with the Synopsys Coverity connect instance.")
    private String credentialsId;

    @Nullable
    @HelpMarkdown("Specify the name of the Coverity project the view is associated with.")
    private String projectName;

    @Nullable
    @HelpMarkdown("Specify the name of the Coverity view that you would like to check for issues.")
    private String viewName;

    @Nullable
    @HelpMarkdown("If checked, will return the number of issues discovered in the specified Coverity view instead of throwing an exception.")
    private Boolean returnIssueCount;

    @Nullable
    @HelpMarkdown("If checked, will mark the stage Unstable but otherwise allow the pipeline to proceed instead of throwing an exception.  \r\n"
                      + "As a byproduct, this also allows the step to return the issue count. Use returnIssueCount if you want to make this behavior more explicit.")
    private Boolean markUnstable;

    @DataBoundConstructor
    public CheckForIssuesStep() {
        // All fields are optional, so this constructor exists only to prevent some versions of the pipeline syntax generator from failing
    }

    public String getCredentialsId() {
        if (StringUtils.isNotBlank(credentialsId)) {
            return credentialsId;
        }
        return null;
    }

    @DataBoundSetter
    public void setCredentialsId(String credentialsId) {
        this.credentialsId = credentialsId;
    }

    public Boolean getReturnIssueCount() {
        if (Boolean.FALSE.equals(returnIssueCount)) {
            return null;
        }
        return returnIssueCount;
    }

    @DataBoundSetter
    public void setReturnIssueCount(Boolean returnIssueCount) {
        this.returnIssueCount = returnIssueCount;
    }

    public String getCoverityInstanceUrl() {
        if (StringUtils.isBlank(coverityInstanceUrl)) {
            return null;
        }
        return coverityInstanceUrl;
    }

    @DataBoundSetter
    public void setCoverityInstanceUrl(String coverityInstanceUrl) {
        this.coverityInstanceUrl = coverityInstanceUrl;
    }

    public String getProjectName() {
        if (StringUtils.isBlank(projectName)) {
            return null;
        }
        return projectName;
    }

    @DataBoundSetter
    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }

    public String getViewName() {
        if (StringUtils.isBlank(viewName)) {
            return null;
        }
        return viewName;
    }

    @DataBoundSetter
    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public Boolean getMarkUnstable() {
        if (Boolean.FALSE.equals(markUnstable)) {
            return null;
        }
        return markUnstable;
    }

    @DataBoundSetter
    public void setMarkUnstable(Boolean markUnstable) {
        this.markUnstable = markUnstable;
    }

    @Override
    public StepExecution start(StepContext context) throws Exception {
        return new Execution(context);
    }

    @Symbol(PIPELINE_NAME)
    @Extension(optional = true)
    public static final class DescriptorImpl extends StepDescriptor {
        private final CoverityConnectionFieldHelper coverityConnectionFieldHelper;
        private final ProjectStreamFieldHelper projectStreamFieldHelper;
        private final IssueViewFieldHelper issueViewFieldHelper;
        private final SynopsysCoverityCredentialsHelper credentialsHelper;

        public DescriptorImpl() {
            Slf4jIntLogger slf4jIntLogger = new Slf4jIntLogger(LoggerFactory.getLogger(this.getClass()));
            coverityConnectionFieldHelper = new CoverityConnectionFieldHelper(slf4jIntLogger);
            projectStreamFieldHelper = new ProjectStreamFieldHelper(slf4jIntLogger);
            issueViewFieldHelper = new IssueViewFieldHelper(slf4jIntLogger);
            credentialsHelper = new SynopsysCoverityCredentialsHelper(slf4jIntLogger, JenkinsWrapper.initializeFromJenkinsJVM());
        }

        @Override
        public Set<? extends Class<?>> getRequiredContext() {
            return new HashSet<>(Arrays.asList(TaskListener.class, EnvVars.class));
        }

        @Override
        public String getFunctionName() {
            return PIPELINE_NAME;
        }

        @Nonnull
        @Override
        public String getDisplayName() {
            return DISPLAY_NAME;
        }

        public ListBoxModel doFillCoverityInstanceUrlItems() {
            return coverityConnectionFieldHelper.doFillCoverityInstanceUrlItems();
        }

        public FormValidation doCheckCoverityInstanceUrl(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId
        ) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrl(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public ListBoxModel doFillCredentialsIdItems() {
            return credentialsHelper.listSupportedCredentials();
        }

        public ListBoxModel doFillProjectNameItems(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter("updateNow") boolean updateNow
        ) throws InterruptedException {
            if (updateNow) {
                projectStreamFieldHelper.updateNow(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
            }
            return projectStreamFieldHelper.getProjectNamesForListBox(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public FormValidation doCheckProjectName(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId
        ) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public ListBoxModel doFillViewNameItems(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter("updateNow") boolean updateNow
        ) throws InterruptedException {
            if (updateNow) {
                issueViewFieldHelper.updateNow(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
            }
            return issueViewFieldHelper.getViewNamesForListBox(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public FormValidation doCheckViewName(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId
        ) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

    }

    public class Execution extends SynchronousNonBlockingStepExecution<Integer> {
        private static final long serialVersionUID = -5807577350749324767L;
        private final transient TaskListener listener;
        private final transient EnvVars envVars;
        private final transient Node node;
        private final transient Launcher launcher;
        private final transient Run<?, ?> run;
        private final transient FlowNode flowNode;

        protected Execution(@Nonnull StepContext context) throws InterruptedException, IOException {
            super(context);
            listener = context.get(TaskListener.class);
            envVars = context.get(EnvVars.class);
            node = context.get(Node.class);
            launcher = context.get(Launcher.class);
            run = context.get(Run.class);
            flowNode = context.get(FlowNode.class);
        }

        @Override
        protected Integer run() throws Exception {
            CoverityWorkflowStepFactory coverityWorkflowStepFactory = new CoverityWorkflowStepFactory(envVars, node, launcher, listener);
            CoverityJenkinsIntLogger logger = coverityWorkflowStepFactory.getOrCreateLogger();
            IntEnvironmentVariables intEnvironmentVariables = coverityWorkflowStepFactory.getOrCreateEnvironmentVariables();
            String unresolvedCoverityInstanceUrl = getRequiredValueOrDie(coverityInstanceUrl, FIELD_COVERITY_INSTANCE_URL, JenkinsCoverityEnvironmentVariable.COVERITY_URL, intEnvironmentVariables::getValue);
            String resolvedCoverityInstanceUrl = Util.replaceMacro(unresolvedCoverityInstanceUrl, intEnvironmentVariables.getVariables());

            String unresolvedProjectName = getRequiredValueOrDie(projectName, FIELD_PROJECT_NAME, JenkinsCoverityEnvironmentVariable.COVERITY_PROJECT, intEnvironmentVariables::getValue);
            String resolvedProjectName = Util.replaceMacro(unresolvedProjectName, intEnvironmentVariables.getVariables());

            String unresolvedViewName = getRequiredValueOrDie(viewName, FIELD_VIEW_NAME, JenkinsCoverityEnvironmentVariable.COVERITY_VIEW, intEnvironmentVariables::getValue);
            String resolvedViewName = Util.replaceMacro(unresolvedViewName, intEnvironmentVariables.getVariables());

            JenkinsVersionHelper jenkinsVersionHelper = JenkinsWrapper.initializeFromJenkinsJVM().getVersionHelper();

            String resolvedCredentialsId;
            Optional<String> possibleCredentialsId = getValueFromStepOrEnvironment(credentialsId, JenkinsCoverityEnvironmentVariable.CREDENTIALS_ID, intEnvironmentVariables::getValue);
            if (possibleCredentialsId.isPresent()) {
                resolvedCredentialsId = possibleCredentialsId.get();
            } else {
                CoverityConnectInstance coverityConnectInstance = coverityWorkflowStepFactory.getCoverityConnectInstanceFromUrl(resolvedCoverityInstanceUrl);
                resolvedCredentialsId = coverityConnectInstance.getDefaultCredentialsId();
            }

            CheckForIssuesStepWorkflow checkForIssuesStepWorkflow = new CheckForIssuesStepWorkflow(logger,
                jenkinsVersionHelper,
                () -> coverityWorkflowStepFactory.getWebServiceFactoryFromUrl(resolvedCoverityInstanceUrl, resolvedCredentialsId),
                coverityWorkflowStepFactory,
                resolvedCoverityInstanceUrl,
                resolvedCredentialsId,
                resolvedProjectName,
                resolvedViewName,
                returnIssueCount,
                markUnstable,
                run,
                flowNode);
            return checkForIssuesStepWorkflow.perform();
        }

        private Optional<String> getValueFromStepOrEnvironment(String pipelineParameter, JenkinsCoverityEnvironmentVariable environmentVariable, UnaryOperator<String> getter) {
            if (StringUtils.isNotBlank(pipelineParameter)) {
                return Optional.of(pipelineParameter);
            }

            String valueFromEnvironmentVariable = getter.apply(environmentVariable.toString());
            if (StringUtils.isNotBlank(valueFromEnvironmentVariable)) {
                return Optional.of(valueFromEnvironmentVariable);
            }

            return Optional.empty();
        }

        private String getRequiredValueOrDie(String pipelineParameter, String parameterName, JenkinsCoverityEnvironmentVariable environmentVariable, UnaryOperator<String> getter) throws AbortException {
            return getValueFromStepOrEnvironment(pipelineParameter, environmentVariable, getter)
                       .orElseThrow(() -> new AbortException( "Coverity issue check failed because required parameter " + parameterName + " was not set. "
                                                                  + "Please set " + parameterName + " or populate $" + environmentVariable.toString() + " with the desired value."));
        }

    }
}

## 内容6
### 文件路径：
src/main/java/com/synopsys/integration/jenkins/coverity/extensions/wrap/CoverityEnvironmentWrapper.java
### 代码内容：
package com.synopsys.integration.jenkins.coverity.extensions.wrap;

import static com.synopsys.integration.jenkins.coverity.JenkinsCoverityEnvironmentVariable.TEMPORARY_AUTH_KEY_PATH;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.jenkinsci.Symbol;
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;
import org.kohsuke.stapler.QueryParameter;
import org.slf4j.LoggerFactory;

import com.synopsys.integration.jenkins.PasswordMaskingOutputStream;
import com.synopsys.integration.jenkins.annotations.HelpMarkdown;
import com.synopsys.integration.jenkins.coverity.CoverityJenkinsIntLogger;
import com.synopsys.integration.jenkins.coverity.GlobalValueHelper;
import com.synopsys.integration.jenkins.coverity.JenkinsCoverityEnvironmentVariable;
import com.synopsys.integration.jenkins.coverity.SynopsysCoverityCredentialsHelper;
import com.synopsys.integration.jenkins.coverity.extensions.ConfigureChangeSetPatterns;
import com.synopsys.integration.jenkins.coverity.extensions.global.CoverityConnectInstance;
import com.synopsys.integration.jenkins.coverity.extensions.utils.CoverityConnectionFieldHelper;
import com.synopsys.integration.jenkins.coverity.extensions.utils.IssueViewFieldHelper;
import com.synopsys.integration.jenkins.coverity.extensions.utils.ProjectStreamFieldHelper;
import com.synopsys.integration.jenkins.coverity.stepworkflow.CleanUpWorkflowService;
import com.synopsys.integration.jenkins.coverity.stepworkflow.CoverityWorkflowStepFactory;
import com.synopsys.integration.jenkins.wrapper.JenkinsVersionHelper;
import com.synopsys.integration.jenkins.wrapper.JenkinsWrapper;
import com.synopsys.integration.log.SilentIntLogger;
import com.synopsys.integration.log.Slf4jIntLogger;
import com.synopsys.integration.util.IntEnvironmentVariables;

import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractProject;
import hudson.model.Computer;
import hudson.model.Node;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.scm.ChangeLogSet;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.util.ComboBoxModel;
import hudson.util.FormValidation;
import hudson.util.ListBoxModel;
import jenkins.tasks.SimpleBuildWrapper;

public class CoverityEnvironmentWrapper extends SimpleBuildWrapper {
    // Jenkins directly serializes the names of the fields, so they are an important part of the plugin's API.
    // Be aware by changing a field name, you will also need to change these strings and will likely break previous implementations.
    // Jenkins Common provides convenient access to the XSTREAM instance that Jenkins uses to serialize the classes, you can use the serialization methods on that class to rename fields without breaking them.
    // --rotte MAY 2021
    public static final String FIELD_COVERITY_INSTANCE_URL = "coverityInstanceUrl";
    public static final String FIELD_PROJECT_NAME = "projectName";
    public static final String FIELD_STREAM_NAME = "streamName";
    public static final String NESTED_DESCRIPTOR_CHECK_FOR_ISSUES = "checkForIssuesInView";
    public static final String NESTED_DESCRIPTOR_CONFIGURE_CHANGE_SET_PATTERNS = "configureChangeSetPatterns";
    public static final String NESTED_DESCRIPTOR_COVERITY_RUN_CONFIGURATION = "coverityRunConfiguration";
    public static final String FIELD_ON_COMMAND_FAILURE = "onCommandFailure";
    public static final String FIELD_CLEAN_UP_ACTION = "cleanUpAction";
    public static final String FIELD_CREDENTIALS_ID = "credentialsId";

    @HelpMarkdown("Specify which Synopsys Coverity connect instance to run this job against.")
    private final String coverityInstanceUrl;
    private final String coverityPassphrase;

    // Any field set by a DataBoundSetter should be explicitly declared as nullable to avoid NPEs
    @Nullable
    @HelpMarkdown("Specify the name of the Coverity project.  \r\n"
                      + "The resulting project name is stored in the $COV_PROJECT environment variable, and will affect both the full and incremental analysis.")
    private String projectName;

    @Nullable
    @HelpMarkdown("Specify the name of the Coverity stream that you would like to use for the commands.  \r\n"
                      + "The resulting stream name is stored in the $COV_STREAM environment variable, and will affect both the full and incremental analysis.")
    private String streamName;

    @Nullable
    @HelpMarkdown("Specify the name of the Coverity view that you would like to check for issues.  \r\n"
                      + "The resulting view name is stored in the $COV_VIEW environment variable, and affects checking for issues in both the full and incremental analysis, if configured.")
    private String viewName;

    @Nullable
    private ConfigureChangeSetPatterns configureChangeSetPatterns;

    @Nullable
    private Boolean createMissingProjectsAndStreams;

    @Nullable
    @HelpMarkdown("Specify the credentials to use with the Synopsys Coverity connect instance.")
    private String credentialsId;

    @DataBoundConstructor
    public CoverityEnvironmentWrapper(String coverityInstanceUrl) {
        this.coverityInstanceUrl = coverityInstanceUrl;
        this.coverityPassphrase = GlobalValueHelper.getCoverityInstanceWithUrl(new SilentIntLogger(), coverityInstanceUrl)
                                      .flatMap(coverityConnectInstance -> coverityConnectInstance.getPassphrase(credentialsId))
                                      .orElse(StringUtils.EMPTY);
    }

    public Boolean getCreateMissingProjectsAndStreams() {
        if (Boolean.FALSE.equals(createMissingProjectsAndStreams)) {
            return null;
        }
        return createMissingProjectsAndStreams;
    }

    @DataBoundSetter
    public void setCreateMissingProjectsAndStreams(@QueryParameter("createMissingProjectsAndStreams") Boolean createMissingProjectsAndStreams) {
        this.createMissingProjectsAndStreams = createMissingProjectsAndStreams;
    }

    public String getCoverityInstanceUrl() {
        return coverityInstanceUrl;
    }

    public String getProjectName() {
        return projectName;
    }

    @DataBoundSetter
    public void setProjectName(@QueryParameter("projectName") String projectName) {
        this.projectName = projectName;
    }

    public String getStreamName() {
        return streamName;
    }

    @DataBoundSetter
    public void setStreamName(@QueryParameter("streamName") String streamName) {
        this.streamName = streamName;
    }

    public String getViewName() {
        return viewName;
    }

    @DataBoundSetter
    public void setViewName(@QueryParameter("viewName") String viewName) {
        this.viewName = viewName;
    }

    public ConfigureChangeSetPatterns getConfigureChangeSetPatterns() {
        return configureChangeSetPatterns;
    }

    @DataBoundSetter
    public void setConfigureChangeSetPatterns(@QueryParameter("configureChangeSetPatterns") ConfigureChangeSetPatterns configureChangeSetPatterns) {
        this.configureChangeSetPatterns = configureChangeSetPatterns;
    }

    public String getCredentialsId() {
        if (StringUtils.isNotBlank(credentialsId)) {
            return credentialsId;
        }
        return null;
    }

    @DataBoundSetter
    public void setCredentialsId(String credentialsId) {
        this.credentialsId = credentialsId;
    }

    @Override
    public void setUp(Context context, Run<?, ?> build, FilePath workspace, Launcher launcher, TaskListener listener, EnvVars initialEnvironment) throws IOException, InterruptedException {
        Node node = Optional.ofNullable(workspace.toComputer())
                        .map(Computer::getNode)
                        .orElse(null);
        RunWrapper runWrapper = new RunWrapper(build, true);

        CoverityWorkflowStepFactory coverityWorkflowStepFactory = new CoverityWorkflowStepFactory(initialEnvironment, node, launcher, listener);
        CoverityJenkinsIntLogger logger = coverityWorkflowStepFactory.getOrCreateLogger();
        JenkinsVersionHelper jenkinsVersionHelper = JenkinsWrapper.initializeFromJenkinsJVM().getVersionHelper();
        List<ChangeLogSet<?>> changeLogSets;
        try {
            changeLogSets = runWrapper.getChangeSets();
        } catch (Exception e) {
            logger.warn(String.format("WARNING: Synopsys Coverity for Jenkins could not determine the change set, %s will be empty and %s will be 0.",
                JenkinsCoverityEnvironmentVariable.CHANGE_SET,
                JenkinsCoverityEnvironmentVariable.CHANGE_SET_SIZE));

            changeLogSets = Collections.emptyList();
        }

        String resolvedCredentialsId;
        if (credentialsId != null) {
            resolvedCredentialsId = credentialsId;
        } else {
            CoverityConnectInstance coverityConnectInstance = coverityWorkflowStepFactory.getCoverityConnectInstanceFromUrl(coverityInstanceUrl);
            resolvedCredentialsId = coverityConnectInstance.getDefaultCredentialsId();
        }

        CoverityEnvironmentWrapperStepWorkflow coverityEnvironmentWrapperStepWorkflow = new CoverityEnvironmentWrapperStepWorkflow(
            logger,
            jenkinsVersionHelper,
            () -> coverityWorkflowStepFactory.getWebServiceFactoryFromUrl(coverityInstanceUrl, resolvedCredentialsId),
            coverityWorkflowStepFactory,
            context,
            workspace.getRemote(),
            coverityInstanceUrl,
            resolvedCredentialsId,
            projectName,
            streamName,
            viewName,
            createMissingProjectsAndStreams,
            changeLogSets,
            configureChangeSetPatterns
        );
        Boolean environmentInjectedSuccessfully = coverityEnvironmentWrapperStepWorkflow.perform();
        if (Boolean.TRUE.equals(environmentInjectedSuccessfully)) {
            logger.info("Coverity environment injected successfully.");
        }

        context.setDisposer(new DisposerImpl((HashMap<String, String>) coverityWorkflowStepFactory.getOrCreateEnvironmentVariables().getVariables()));
    }

    @Override
    public DescriptorImpl getDescriptor() {
        return (DescriptorImpl) super.getDescriptor();
    }

    @Override
    public ConsoleLogFilter createLoggerDecorator(@Nonnull Run<?, ?> build) {
        return new FilterImpl(coverityPassphrase);
    }

    @Symbol("withCoverityEnvironment")
    @Extension
    public static final class DescriptorImpl extends BuildWrapperDescriptor {
        private final CoverityConnectionFieldHelper coverityConnectionFieldHelper;
        private final ProjectStreamFieldHelper projectStreamFieldHelper;
        private final SynopsysCoverityCredentialsHelper credentialsHelper;
        private final IssueViewFieldHelper issueViewFieldHelper;

        public DescriptorImpl() {
            super(CoverityEnvironmentWrapper.class);
            load();

            Slf4jIntLogger slf4jIntLogger = new Slf4jIntLogger(LoggerFactory.getLogger(this.getClass()));
            coverityConnectionFieldHelper = new CoverityConnectionFieldHelper(slf4jIntLogger);
            projectStreamFieldHelper = new ProjectStreamFieldHelper(slf4jIntLogger);
            issueViewFieldHelper = new IssueViewFieldHelper(slf4jIntLogger);
            credentialsHelper = new SynopsysCoverityCredentialsHelper(slf4jIntLogger, JenkinsWrapper.initializeFromJenkinsJVM());
        }

        public ListBoxModel doFillCoverityInstanceUrlItems() {
            return coverityConnectionFieldHelper.doFillCoverityInstanceUrlItems();
        }

        public FormValidation doCheckCoverityInstanceUrl(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId
        ) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrl(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public ListBoxModel doFillCredentialsIdItems() {
            return credentialsHelper.listSupportedCredentials();
        }

        public ComboBoxModel doFillProjectNameItems(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter("updateNow") boolean updateNow
        ) throws InterruptedException {
            if (updateNow) {
                projectStreamFieldHelper.updateNow(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
            }
            return projectStreamFieldHelper.getProjectNamesForComboBox(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public FormValidation doCheckProjectName(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId
        ) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public ComboBoxModel doFillStreamNameItems(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter(FIELD_PROJECT_NAME) String projectName
        ) throws InterruptedException {
            return projectStreamFieldHelper.getStreamNamesForComboBox(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId, projectName);
        }

        public FormValidation doCheckStreamName(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrlIgnoreMessage(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public ListBoxModel doFillViewNameItems(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId,
            @QueryParameter("updateNow") boolean updateNow
        ) throws InterruptedException {
            if (updateNow) {
                issueViewFieldHelper.updateNow(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
            }
            return issueViewFieldHelper.getViewNamesForListBox(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        public FormValidation doCheckViewName(
            @QueryParameter(FIELD_COVERITY_INSTANCE_URL) String coverityInstanceUrl,
            @QueryParameter(FIELD_CREDENTIALS_ID) String credentialsId) {
            return coverityConnectionFieldHelper.doCheckCoverityInstanceUrl(coverityInstanceUrl, StringUtils.isNotBlank(credentialsId), credentialsId);
        }

        @Override
        public boolean isApplicable(AbstractProject<?, ?> item) {
            return true;
        }

        @Override
        public String getDisplayName() {
            return "Inject Coverity environment into the build process";
        }
    }

    private static final class FilterImpl extends ConsoleLogFilter implements Serializable {
        private static final long serialVersionUID = 1787519634824445328L;
        private final String passwordToMask;

        public FilterImpl(String passwordToMask) {
            this.passwordToMask = passwordToMask;
        }

        @Override
        public OutputStream decorateLogger(Run ignored, OutputStream logger) {
            return new PasswordMaskingOutputStream(logger, passwordToMask);
        }
    }

    private static final class DisposerImpl extends SimpleBuildWrapper.Disposer {
        private static final long serialVersionUID = 4771346213830683656L;
        private final HashMap<String, String> environmentVariables;

        public DisposerImpl(HashMap<String, String> intEnvironmentVariables) {
            this.environmentVariables = intEnvironmentVariables;
        }

        @Override
        public void tearDown(Run<?, ?> build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException {
            IntEnvironmentVariables intEnvironmentVariables = IntEnvironmentVariables.empty();
            intEnvironmentVariables.putAll(environmentVariables);
            CoverityJenkinsIntLogger logger = CoverityJenkinsIntLogger.initializeLogger(listener, intEnvironmentVariables);
            CleanUpWorkflowService cleanUpWorkflowService = new CleanUpWorkflowService(logger);

            String authKeyPath = intEnvironmentVariables.getValue(TEMPORARY_AUTH_KEY_PATH.toString());
            if (StringUtils.isNotBlank(authKeyPath)) {
                FilePath authKeyFile = new FilePath(launcher.getChannel(), authKeyPath);
                cleanUpWorkflowService.cleanUpAuthenticationFile(authKeyFile);
            }
        }
    }

}


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
inlong-manager/manager-workflow/src/main/java/org/apache/inlong/manager/workflow/core/impl/ProcessServiceImpl.java
### 代码内容：
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.inlong.manager.workflow.core.impl;

import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
import org.apache.inlong.manager.common.enums.ProcessStatus;
import org.apache.inlong.manager.common.enums.TaskStatus;
import org.apache.inlong.manager.common.util.Preconditions;
import org.apache.inlong.manager.dao.entity.WorkflowProcessEntity;
import org.apache.inlong.manager.dao.entity.WorkflowTaskEntity;
import org.apache.inlong.manager.dao.mapper.WorkflowTaskEntityMapper;
import org.apache.inlong.manager.pojo.workflow.form.process.ProcessForm;
import org.apache.inlong.manager.workflow.WorkflowAction;
import org.apache.inlong.manager.workflow.WorkflowContext;
import org.apache.inlong.manager.workflow.core.ProcessService;
import org.apache.inlong.manager.workflow.core.ProcessorExecutor;
import org.apache.inlong.manager.workflow.core.WorkflowContextBuilder;
import org.apache.inlong.manager.workflow.definition.WorkflowTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * WorkflowProcess service
 */
@Service
@Slf4j
public class ProcessServiceImpl implements ProcessService {

    @Autowired
    private ProcessorExecutor processorExecutor;
    @Autowired
    private WorkflowTaskEntityMapper taskEntityMapper;
    @Autowired
    private WorkflowContextBuilder workflowContextBuilder;

    @Override
    public WorkflowContext start(String name, String applicant, ProcessForm form) {
        Preconditions.expectNotBlank(name, ErrorCodeEnum.INVALID_PARAMETER, "process name cannot be null");
        Preconditions.expectNotBlank(applicant, ErrorCodeEnum.INVALID_PARAMETER, "applicant cannot be null");
        Preconditions.expectNotNull(form, "form cannot be null");

        // build context
        WorkflowContext context = workflowContextBuilder.buildContextForProcess(name, applicant, form);
        this.processorExecutor.executeStart(context.getProcess().getStartEvent(), context);
        return context;
    }

    @Override
    public WorkflowContext continueProcess(Integer processId, String operator, String remark) {
        Preconditions.expectNotBlank(operator, ErrorCodeEnum.INVALID_PARAMETER, "operator cannot be null");
        Preconditions.expectNotNull(processId, "processId cannot be null");
        WorkflowContext context = workflowContextBuilder.buildContextForProcess(processId);
        WorkflowProcessEntity processEntity = context.getProcessEntity();
        ProcessStatus processStatus = ProcessStatus.valueOf(processEntity.getStatus());
        Preconditions.expectTrue(processStatus == ProcessStatus.PROCESSING,
                String.format("processId=%s should be in processing", processId));
        List<WorkflowTaskEntity> startElements = Lists.newArrayList();
        startElements.addAll(taskEntityMapper.selectByProcess(processId, TaskStatus.PENDING));
        startElements.addAll(taskEntityMapper.selectByProcess(processId, TaskStatus.FAILED));
        for (WorkflowTaskEntity taskEntity : startElements) {
            String taskName = taskEntity.getName();
            WorkflowTask task = context.getProcess().getTaskByName(taskName);
            context.setActionContext(new WorkflowContext.ActionContext()
                    .setAction(WorkflowAction.COMPLETE)
                    .setTaskEntity(taskEntity)
                    .setOperator(operator)
                    .setRemark(remark)
                    .setTask(task));
            this.processorExecutor.executeStart(task, context);
        }
        return context;
    }

    @Override
    public WorkflowContext cancel(Integer processId, String operator, String remark) {
        Preconditions.expectNotBlank(operator, ErrorCodeEnum.INVALID_PARAMETER, "operator cannot be null");
        Preconditions.expectNotNull(processId, "processId cannot be null");

        WorkflowContext context = workflowContextBuilder.buildContextForProcess(processId);
        List<WorkflowTaskEntity> pendingTasks = taskEntityMapper.selectByProcess(processId, TaskStatus.PENDING);
        for (WorkflowTaskEntity taskEntity : pendingTasks) {
            WorkflowTask task = context.getProcess().getTaskByName(taskEntity.getName());
            context.setActionContext(new WorkflowContext.ActionContext()
                    .setAction(WorkflowAction.CANCEL)
                    .setTaskEntity(taskEntity)
                    .setOperator(operator)
                    .setRemark(remark)
                    .setTask(task));
            this.processorExecutor.executeComplete(task, context);
        }

        return context;
    }

}

Output:
【漏洞类型】权限检查缺失
【严重性】高
【漏洞摘要】原始代码在启动、继续和取消工作流时，没有对操作者进行权限检查。攻击者可以通过提供任意用户名来执行这些操作，从而绕过权限控制，拥有不当的访问权限。
【关键代码模式】
- `start` 方法中没有检查操作者权限。
- `continueProcess` 方法中没有检查操作者权限。
- `cancel` 方法中没有检查操作者权限。

【修复方法说明】修复方法通过增加 `checkUser` 方法，在启动、继续和取消工作流之前检查操作者是否具有权限。