com.h3xstream.findbugs.test.service.FindBugsLauncher.java Source code

Java tutorial

Introduction

Here is the source code for com.h3xstream.findbugs.test.service.FindBugsLauncher.java

Source

/**
 * Find Security Bugs
 * Copyright (c) Philippe Arteau, All rights reserved.
 *
 * This library 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.0 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library.
 */
package com.h3xstream.findbugs.test.service;

import static org.mockito.Mockito.mock;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import javax.annotation.concurrent.NotThreadSafe;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.DetectorFactoryCollection;
import edu.umd.cs.findbugs.FindBugs2;
import edu.umd.cs.findbugs.FindBugsProgress;
import edu.umd.cs.findbugs.Plugin;
import edu.umd.cs.findbugs.PluginException;
import edu.umd.cs.findbugs.Project;
import edu.umd.cs.findbugs.config.ProjectFilterSettings;
import edu.umd.cs.findbugs.config.UserPreferences;

@NotThreadSafe
public class FindBugsLauncher {

    private static final Logger log = LoggerFactory.getLogger(FindBugsLauncher.class);

    static Plugin loadedPlugin;

    /**
     * Launch an analysis on the given source files.
     *
     * @param classFiles
     * @param bugReporter
     * @throws java.io.IOException
     * @throws InterruptedException
     * @throws edu.umd.cs.findbugs.PluginException
     * @throws URISyntaxException 
     *
     */
    public void analyze(String[] classFiles, BugReporter bugReporter) throws IOException, InterruptedException,
            PluginException, NoSuchFieldException, IllegalAccessException, URISyntaxException {
        analyze(classFiles, new String[] {}, bugReporter);
    }

    /**
     * Launch an analysis on the given source files.
     *
     * @param classFiles
     * @param classPaths
     * @param bugReporter
     * @throws java.io.IOException
     * @throws InterruptedException
     * @throws edu.umd.cs.findbugs.PluginException
     * @throws URISyntaxException
     *
     */
    public void analyze(String[] classFiles, String[] classPaths, BugReporter bugReporter)
            throws IOException, InterruptedException, PluginException, NoSuchFieldException, IllegalAccessException,
            URISyntaxException {
        Project project = new Project();
        project.setProjectName("automate-test-project");
        for (String file : classFiles) {
            project.addFile(file);
        }

        // Add classpath list to project's auxclasspath
        for (String classpath : classPaths) {
            project.addAuxClasspathEntry(classpath);
        }

        if (loadedPlugin == null) {
            //Initialize the plugin base on the findbugs.xml
            byte[] archive = buildFakePluginJar();

            File f = new File(System.getProperty("java.io.tmpdir"), "plugin.jar");
            log.info("Writing " + f.getCanonicalPath());
            f.deleteOnExit();
            FileOutputStream out = new FileOutputStream(f);
            out.write(archive);
            out.close();

            loadedPlugin = Plugin.loadCustomPlugin(f.toURI().toURL(), project);
        }

        //FindBugs engine
        FindBugs2 engine = new FindBugs2();
        engine.setNoClassOk(true);
        engine.setMergeSimilarWarnings(false);
        engine.setBugReporter(bugReporter);
        engine.setProject(project);
        engine.setProgressCallback(mock(FindBugsProgress.class));

        engine.setDetectorFactoryCollection(DetectorFactoryCollection.instance());

        //User preferences set to miss no bugs report
        UserPreferences prefs = UserPreferences.createDefaultUserPreferences();

        ProjectFilterSettings filter = prefs.getFilterSettings();
        filter.setMinRank(20);
        filter.setDisplayFalseWarnings(true);
        filter.setMinPriority("Low");

        engine.setUserPreferences(prefs);

        log.info("Analyzing... {}", classFiles);
        engine.execute();
    }

    /**
     * The minimum requirement to have a "valid" archive plugin is to include
     * findbugs.xml, messages.xml and MANIFEST.MF files. The rest of the
     * resources are load using the parent ClassLoader (Not requires to be in
     * the jar).
     * <p>
     * Instead of building a file on disk, the result of the stream is kept in
     * memory and return as a byte array.
     *
     * @return
     * @throws IOException
     * @throws URISyntaxException 
     */
    private byte[] buildFakePluginJar() throws IOException, URISyntaxException {
        ClassLoader cl = getClass().getClassLoader();

        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        JarOutputStream jar = new JarOutputStream(buffer);

        final URL metadata = cl.getResource("metadata");
        if (metadata != null) {
            final File dir = new File(metadata.toURI());

            //Add files to the jar stream
            addFilesToStream(cl, jar, dir, "");
        }
        jar.finish();
        jar.close();

        return buffer.toByteArray();
    }

    private void addFilesToStream(final ClassLoader cl, final JarOutputStream jar, final File dir,
            final String path) throws IOException {
        for (final File nextFile : dir.listFiles()) {
            if (nextFile.isFile()) {
                final String resource = path + nextFile.getName();
                jar.putNextEntry(new ZipEntry(resource));
                jar.write(IOUtils.toByteArray(cl.getResourceAsStream("metadata/" + resource)));
            } else {
                addFilesToStream(cl, jar, nextFile, path + nextFile.getName() + "/");
            }
        }
    }
}