Coverage Report - org.owasp.dependencycheck.App
 
Classes in this File Line Coverage Branch Coverage Complexity
App
0%
0/178
0%
0/120
16.75
 
 1  
 /*
 2  
  * This file is part of dependency-check-cli.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  *
 16  
  * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
 17  
  */
 18  
 package org.owasp.dependencycheck;
 19  
 
 20  
 import java.io.File;
 21  
 import java.io.FileNotFoundException;
 22  
 import java.io.IOException;
 23  
 import java.io.InputStream;
 24  
 import java.util.ArrayList;
 25  
 import java.util.Arrays;
 26  
 import java.util.HashSet;
 27  
 import java.util.List;
 28  
 import java.util.Set;
 29  
 import java.util.logging.Level;
 30  
 import java.util.logging.Logger;
 31  
 import org.apache.commons.cli.ParseException;
 32  
 import org.owasp.dependencycheck.data.nvdcve.CveDB;
 33  
 import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
 34  
 import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
 35  
 import org.owasp.dependencycheck.dependency.Dependency;
 36  
 import org.owasp.dependencycheck.org.apache.tools.ant.DirectoryScanner;
 37  
 import org.owasp.dependencycheck.reporting.ReportGenerator;
 38  
 import org.owasp.dependencycheck.utils.LogUtils;
 39  
 import org.owasp.dependencycheck.utils.Settings;
 40  
 
 41  
 /**
 42  
  * The command line interface for the DependencyCheck application.
 43  
  *
 44  
  * @author Jeremy Long <jeremy.long@owasp.org>
 45  
  */
 46  
 public class App {
 47  
 
 48  
     /**
 49  
      * The location of the log properties configuration file.
 50  
      */
 51  
     private static final String LOG_PROPERTIES_FILE = "log.properties";
 52  
 
 53  
     /**
 54  
      * The logger.
 55  
      */
 56  0
     private static final Logger LOGGER = Logger.getLogger(App.class.getName());
 57  
 
 58  
     /**
 59  
      * The main method for the application.
 60  
      *
 61  
      * @param args the command line arguments
 62  
      */
 63  
     public static void main(String[] args) {
 64  
         try {
 65  0
             Settings.initialize();
 66  0
             final App app = new App();
 67  0
             app.run(args);
 68  
         } finally {
 69  0
             Settings.cleanup(true);
 70  0
         }
 71  0
     }
 72  
 
 73  
     /**
 74  
      * Main CLI entry-point into the application.
 75  
      *
 76  
      * @param args the command line arguments
 77  
      */
 78  
     public void run(String[] args) {
 79  0
         final CliParser cli = new CliParser();
 80  
 
 81  
         try {
 82  0
             cli.parse(args);
 83  0
         } catch (FileNotFoundException ex) {
 84  0
             System.err.println(ex.getMessage());
 85  0
             cli.printHelp();
 86  0
             return;
 87  0
         } catch (ParseException ex) {
 88  0
             System.err.println(ex.getMessage());
 89  0
             cli.printHelp();
 90  0
             return;
 91  0
         }
 92  
 
 93  0
         final InputStream in = App.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
 94  0
         LogUtils.prepareLogger(in, cli.getVerboseLog());
 95  
 
 96  0
         if (cli.isGetVersion()) {
 97  0
             cli.printVersionInfo();
 98  0
         } else if (cli.isRunScan()) {
 99  0
             populateSettings(cli);
 100  
             try {
 101  0
                 runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getApplicationName(), cli.getScanFiles(), cli.getExcludeList());
 102  0
             } catch (InvalidScanPathException ex) {
 103  0
                 Logger.getLogger(App.class.getName()).log(Level.SEVERE, "An invalid scan path was detected; unable to scan '//*' paths");
 104  0
             }
 105  
         } else {
 106  0
             cli.printHelp();
 107  
         }
 108  0
     }
 109  
 
 110  
     /**
 111  
      * Scans the specified directories and writes the dependency reports to the reportDirectory.
 112  
      *
 113  
      * @param reportDirectory the path to the directory where the reports will be written
 114  
      * @param outputFormat the output format of the report
 115  
      * @param applicationName the application name for the report
 116  
      * @param files the files/directories to scan
 117  
      * @param excludes the patterns for files/directories to exclude
 118  
      *
 119  
      * @throws InvalidScanPathException thrown if the path to scan starts with "//"
 120  
      */
 121  
     private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
 122  
             String[] excludes) throws InvalidScanPathException {
 123  0
         Engine engine = null;
 124  
         try {
 125  0
             engine = new Engine();
 126  0
             List<String> antStylePaths = new ArrayList<String>();
 127  0
             if (excludes == null || excludes.length == 0) {
 128  0
                 for (String file : files) {
 129  0
                     if (file.contains("*") || file.contains("?")) {
 130  0
                         antStylePaths.add(file);
 131  
                     } else {
 132  0
                         engine.scan(file);
 133  
                     }
 134  
                 }
 135  
             } else {
 136  0
                 antStylePaths = Arrays.asList(files);
 137  
             }
 138  
 
 139  0
             final Set<File> paths = new HashSet<File>();
 140  0
             for (String file : antStylePaths) {
 141  0
                 final DirectoryScanner scanner = new DirectoryScanner();
 142  0
                 String include = file.replace('\\', '/');
 143  
                 File baseDir;
 144  
 
 145  0
                 if (include.startsWith("//")) {
 146  0
                     throw new InvalidScanPathException("Unable to scan paths specified by //");
 147  0
                 } else if (include.startsWith("./")) {
 148  0
                     baseDir = new File(".");
 149  0
                     include = include.substring(2);
 150  0
                 } else if (include.startsWith("/")) {
 151  0
                     baseDir = new File("/");
 152  0
                     include = include.substring(1);
 153  0
                 } else if (include.contains("/")) {
 154  0
                     final int pos = include.indexOf('/');
 155  0
                     final String tmp = include.substring(0, pos);
 156  0
                     if (tmp.contains("*") || tmp.contains("?")) {
 157  0
                         baseDir = new File(".");
 158  
                     } else {
 159  0
                         baseDir = new File(tmp);
 160  0
                         include = include.substring(pos + 1);
 161  
                     }
 162  0
                 } else { //no path info - must just be a file in the working directory
 163  0
                     baseDir = new File(".");
 164  
                 }
 165  0
                 scanner.setBasedir(baseDir);
 166  0
                 scanner.setIncludes(include);
 167  0
                 if (excludes != null && excludes.length > 0) {
 168  0
                     scanner.addExcludes(excludes);
 169  
                 }
 170  0
                 scanner.scan();
 171  0
                 if (scanner.getIncludedFilesCount() > 0) {
 172  0
                     for (String s : scanner.getIncludedFiles()) {
 173  0
                         final File f = new File(baseDir, s);
 174  0
                         paths.add(f);
 175  
                     }
 176  
                 }
 177  0
             }
 178  0
             engine.scan(paths);
 179  
 
 180  0
             engine.analyzeDependencies();
 181  0
             final List<Dependency> dependencies = engine.getDependencies();
 182  0
             DatabaseProperties prop = null;
 183  0
             CveDB cve = null;
 184  
             try {
 185  0
                 cve = new CveDB();
 186  0
                 cve.open();
 187  0
                 prop = cve.getDatabaseProperties();
 188  0
             } catch (DatabaseException ex) {
 189  0
                 LOGGER.log(Level.FINE, "Unable to retrieve DB Properties", ex);
 190  
             } finally {
 191  0
                 if (cve != null) {
 192  0
                     cve.close();
 193  
                 }
 194  
             }
 195  0
             final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
 196  
             try {
 197  0
                 report.generateReports(reportDirectory, outputFormat);
 198  0
             } catch (IOException ex) {
 199  0
                 LOGGER.log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
 200  0
                 LOGGER.log(Level.FINE, null, ex);
 201  0
             } catch (Throwable ex) {
 202  0
                 LOGGER.log(Level.SEVERE, "There was an error while attempting to generate the report.");
 203  0
                 LOGGER.log(Level.FINE, null, ex);
 204  0
             }
 205  0
         } catch (DatabaseException ex) {
 206  0
             LOGGER.log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
 207  0
             LOGGER.log(Level.FINE, "", ex);
 208  
         } finally {
 209  0
             if (engine != null) {
 210  0
                 engine.cleanup();
 211  
             }
 212  
         }
 213  0
     }
 214  
 
 215  
     /**
 216  
      * Updates the global Settings.
 217  
      *
 218  
      * @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding
 219  
      * settings in the core engine.
 220  
      */
 221  
     private void populateSettings(CliParser cli) {
 222  
 
 223  0
         final boolean autoUpdate = cli.isAutoUpdate();
 224  0
         final String connectionTimeout = cli.getConnectionTimeout();
 225  0
         final String proxyServer = cli.getProxyServer();
 226  0
         final String proxyPort = cli.getProxyPort();
 227  0
         final String proxyUser = cli.getProxyUsername();
 228  0
         final String proxyPass = cli.getProxyPassword();
 229  0
         final String dataDirectory = cli.getDataDirectory();
 230  0
         final File propertiesFile = cli.getPropertiesFile();
 231  0
         final String suppressionFile = cli.getSuppressionFile();
 232  0
         final boolean jarDisabled = cli.isJarDisabled();
 233  0
         final boolean archiveDisabled = cli.isArchiveDisabled();
 234  0
         final boolean assemblyDisabled = cli.isAssemblyDisabled();
 235  0
         final boolean nuspecDisabled = cli.isNuspecDisabled();
 236  0
         final boolean nexusDisabled = cli.isNexusDisabled();
 237  0
         final String nexusUrl = cli.getNexusUrl();
 238  0
         final String databaseDriverName = cli.getDatabaseDriverName();
 239  0
         final String databaseDriverPath = cli.getDatabaseDriverPath();
 240  0
         final String connectionString = cli.getConnectionString();
 241  0
         final String databaseUser = cli.getDatabaseUser();
 242  0
         final String databasePassword = cli.getDatabasePassword();
 243  0
         final String additionalZipExtensions = cli.getAdditionalZipExtensions();
 244  0
         final String pathToMono = cli.getPathToMono();
 245  
 
 246  0
         if (propertiesFile != null) {
 247  
             try {
 248  0
                 Settings.mergeProperties(propertiesFile);
 249  0
             } catch (FileNotFoundException ex) {
 250  0
                 final String msg = String.format("Unable to load properties file '%s'", propertiesFile.getPath());
 251  0
                 LOGGER.log(Level.SEVERE, msg);
 252  0
                 LOGGER.log(Level.FINE, null, ex);
 253  0
             } catch (IOException ex) {
 254  0
                 final String msg = String.format("Unable to find properties file '%s'", propertiesFile.getPath());
 255  0
                 LOGGER.log(Level.SEVERE, msg);
 256  0
                 LOGGER.log(Level.FINE, null, ex);
 257  0
             }
 258  
         }
 259  
         // We have to wait until we've merged the properties before attempting to set whether we use
 260  
         // the proxy for Nexus since it could be disabled in the properties, but not explicitly stated
 261  
         // on the command line
 262  0
         final boolean nexusUsesProxy = cli.isNexusUsesProxy();
 263  0
         if (dataDirectory != null) {
 264  0
             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDirectory);
 265  0
         } else if (System.getProperty("basedir") != null) {
 266  0
             final File dataDir = new File(System.getProperty("basedir"), "data");
 267  0
             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
 268  0
         } else {
 269  0
             final File jarPath = new File(App.class.getProtectionDomain().getCodeSource().getLocation().getPath());
 270  0
             final File base = jarPath.getParentFile();
 271  0
             final String sub = Settings.getString(Settings.KEYS.DATA_DIRECTORY);
 272  0
             final File dataDir = new File(base, sub);
 273  0
             Settings.setString(Settings.KEYS.DATA_DIRECTORY, dataDir.getAbsolutePath());
 274  
         }
 275  0
         Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
 276  0
         if (proxyServer != null && !proxyServer.isEmpty()) {
 277  0
             Settings.setString(Settings.KEYS.PROXY_SERVER, proxyServer);
 278  
         }
 279  0
         if (proxyPort != null && !proxyPort.isEmpty()) {
 280  0
             Settings.setString(Settings.KEYS.PROXY_PORT, proxyPort);
 281  
         }
 282  0
         if (proxyUser != null && !proxyUser.isEmpty()) {
 283  0
             Settings.setString(Settings.KEYS.PROXY_USERNAME, proxyUser);
 284  
         }
 285  0
         if (proxyPass != null && !proxyPass.isEmpty()) {
 286  0
             Settings.setString(Settings.KEYS.PROXY_PASSWORD, proxyPass);
 287  
         }
 288  0
         if (connectionTimeout != null && !connectionTimeout.isEmpty()) {
 289  0
             Settings.setString(Settings.KEYS.CONNECTION_TIMEOUT, connectionTimeout);
 290  
         }
 291  0
         if (suppressionFile != null && !suppressionFile.isEmpty()) {
 292  0
             Settings.setString(Settings.KEYS.SUPPRESSION_FILE, suppressionFile);
 293  
         }
 294  
 
 295  
         //File Type Analyzer Settings
 296  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_JAR_ENABLED, !jarDisabled);
 297  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_ARCHIVE_ENABLED, !archiveDisabled);
 298  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_NUSPEC_ENABLED, !nuspecDisabled);
 299  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_ASSEMBLY_ENABLED, !assemblyDisabled);
 300  
 
 301  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, !nexusDisabled);
 302  0
         if (nexusUrl != null && !nexusUrl.isEmpty()) {
 303  0
             Settings.setString(Settings.KEYS.ANALYZER_NEXUS_URL, nexusUrl);
 304  
         }
 305  0
         Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_PROXY, nexusUsesProxy);
 306  0
         if (databaseDriverName != null && !databaseDriverName.isEmpty()) {
 307  0
             Settings.setString(Settings.KEYS.DB_DRIVER_NAME, databaseDriverName);
 308  
         }
 309  0
         if (databaseDriverPath != null && !databaseDriverPath.isEmpty()) {
 310  0
             Settings.setString(Settings.KEYS.DB_DRIVER_PATH, databaseDriverPath);
 311  
         }
 312  0
         if (connectionString != null && !connectionString.isEmpty()) {
 313  0
             Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
 314  
         }
 315  0
         if (databaseUser != null && !databaseUser.isEmpty()) {
 316  0
             Settings.setString(Settings.KEYS.DB_USER, databaseUser);
 317  
         }
 318  0
         if (databasePassword != null && !databasePassword.isEmpty()) {
 319  0
             Settings.setString(Settings.KEYS.DB_PASSWORD, databasePassword);
 320  
         }
 321  0
         if (additionalZipExtensions != null && !additionalZipExtensions.isEmpty()) {
 322  0
             Settings.setString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS, additionalZipExtensions);
 323  
         }
 324  0
         if (pathToMono != null && !pathToMono.isEmpty()) {
 325  0
             Settings.setString(Settings.KEYS.ANALYZER_ASSEMBLY_MONO_PATH, pathToMono);
 326  
         }
 327  0
     }
 328  
 }