View Javadoc

    1   /*
    2    * This file is part of dependency-check-core.
    3    *
    4    * Dependency-check-core is free software: you can redistribute it and/or modify it
    5    * under the terms of the GNU General Public License as published by the Free
    6    * Software Foundation, either version 3 of the License, or (at your option) any
    7    * later version.
    8    *
    9    * Dependency-check-core is distributed in the hope that it will be useful, but
    10   * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    12   * details.
    13   *
    14   * You should have received a copy of the GNU General Public License along with
    15   * dependency-check-core. If not, see http://www.gnu.org/licenses/.
    16   *
    17   * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
    18   */
    19  package org.owasp.dependencycheck.utils;
    20
    21  import java.io.File;
    22  import java.io.FileInputStream;
    23  import java.io.FileNotFoundException;
    24  import java.io.IOException;
    25  import java.io.InputStream;
    26  import java.io.UnsupportedEncodingException;
    27  import java.net.URLDecoder;
    28  import java.util.Properties;
    29  import java.util.logging.Level;
    30  import java.util.logging.Logger;
    31
    32  /**
    33   * A simple settings container that wraps the dependencycheck.properties file.
    34   *
    35   * @author Jeremy Long (jeremy.long@owasp.org)
    36   */
    37  public final class Settings {
    38
    39      /**
    40       * The collection of keys used within the properties file.
    41       */
    42      public static final class KEYS {
    43
    44          /**
    45           * private constructor because this is a "utility" class containing
    46           * constants
    47           */
    48          private KEYS() {
    49              //do nothing
    50          }
    51          /**
    52           * The properties key indicating whether or not the cached data sources
    53           * should be updated.
    54           */
    55          public static final String AUTO_UPDATE = "autoupdate";
    56          /**
    57           * The database driver class name. If this is not in the properties file
    58           * the embedded database is used.
    59           */
    60          public static final String DB_DRIVER = "database.drive";
    61          /**
    62           * The database connection string. If this is not in the properties file
    63           * the embedded database is used.
    64           */
    65          public static final String DB_CONNECTION_STRING = "database.connectionstring";
    66          /**
    67           * The base path to use for the data directory.
    68           */
    69          public static final String DATA_DIRECTORY = "data.directory";
    70          /**
    71           * The location of the batch update URL. This is a zip file that
    72           * contains the contents of the data directory.
    73           */
    74          public static final String BATCH_UPDATE_URL = "batch.update.url";
    75          /**
    76           * The properties key for the path where the CPE Lucene Index will be
    77           * stored.
    78           */
    79          public static final String CPE_DATA_DIRECTORY = "data.cpe";
    80          /**
    81           * The properties key for the path where the CVE H2 database will be
    82           * stored.
    83           */
    84          public static final String CVE_DATA_DIRECTORY = "data.cve";
    85          /**
    86           * The properties key for the URL to retrieve the "meta" data from about
    87           * the CVE entries.
    88           */
    89          public static final String CVE_META_URL = "cve.url.meta";
    90          /**
    91           * The properties key for the URL to retrieve the recently modified and
    92           * added CVE entries (last 8 days) using the 2.0 schema.
    93           */
    94          public static final String CVE_MODIFIED_20_URL = "cve.url-2.0.modified";
    95          /**
    96           * The properties key for the URL to retrieve the recently modified and
    97           * added CVE entries (last 8 days) using the 1.2 schema.
    98           */
    99          public static final String CVE_MODIFIED_12_URL = "cve.url-1.2.modified";
    100         /**
    101          * The properties key for the URL to retrieve the recently modified and
    102          * added CVE entries (last 8 days).
    103          */
    104         public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
    105         /**
    106          * The properties key for the telling us how many cvr.url.* URLs exists.
    107          * This is used in combination with CVE_BASE_URL to be able to retrieve
    108          * the URLs for all of the files that make up the NVD CVE listing.
    109          */
    110         public static final String CVE_START_YEAR = "cve.startyear";
    111         /**
    112          * The properties key for the CVE schema version 1.2.
    113          */
    114         public static final String CVE_SCHEMA_1_2 = "cve.url-1.2.base";
    115         /**
    116          * The properties key for the CVE schema version 2.0.
    117          */
    118         public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
    119         /**
    120          * The properties key for the proxy url.
    121          */
    122         public static final String PROXY_URL = "proxy.url";
    123         /**
    124          * The properties key for the proxy port - this must be an integer
    125          * value.
    126          */
    127         public static final String PROXY_PORT = "proxy.port";
    128         /**
    129          * The properties key for the proxy username.
    130          */
    131         public static final String PROXY_USERNAME = "proxy.username";
    132         /**
    133          * The properties key for the proxy password.
    134          */
    135         public static final String PROXY_PASSWORD = "proxy.password";
    136         /**
    137          * The properties key for the connection timeout.
    138          */
    139         public static final String CONNECTION_TIMEOUT = "connection.timeout";
    140         /**
    141          * The location of the temporary directory.
    142          */
    143         public static final String TEMP_DIRECTORY = "temp.directory";
    144     }
    145     /**
    146      * The properties file location.
    147      */
    148     private static final String PROPERTIES_FILE = "dependencycheck.properties";
    149     /**
    150      * The singleton instance variable.
    151      */
    152     private static final Settings INSTANCE = new Settings();
    153     /**
    154      * The properties.
    155      */
    156     private Properties props = null;
    157
    158     /**
    159      * Private constructor for the Settings class. This class loads the
    160      * properties files.
    161      */
    162     private Settings() {
    163         InputStream in = null;
    164         props = new Properties();
    165         try {
    166             in = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
    167             props.load(in);
    168         } catch (IOException ex) {
    169             Logger.getLogger(Settings.class.getName()).log(Level.SEVERE, "Unable to load default settings.");
    170             Logger.getLogger(Settings.class.getName()).log(Level.FINE, null, ex);
    171         } finally {
    172             if (in != null) {
    173                 try {
    174                     in.close();
    175                 } catch (IOException ex) {
    176                     Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
    177                 }
    178             }
    179         }
    180     }
    181
    182     /**
    183      * Sets a property value.
    184      *
    185      * @param key the key for the property
    186      * @param value the value for the property
    187      */
    188     public static void setString(String key, String value) {
    189         INSTANCE.props.setProperty(key, value);
    190     }
    191
    192     /**
    193      * Sets a property value.
    194      *
    195      * @param key the key for the property
    196      * @param value the value for the property
    197      */
    198     public static void setBoolean(String key, boolean value) {
    199         if (value) {
    200             INSTANCE.props.setProperty(key, Boolean.TRUE.toString());
    201         } else {
    202             INSTANCE.props.setProperty(key, Boolean.FALSE.toString());
    203         }
    204     }
    205
    206     /**
    207      * Merges a new properties file into the current properties. This method
    208      * allows for the loading of a user provided properties file.<br/><br/>
    209      * Note: even if using this method - system properties will be loaded before
    210      * properties loaded from files.
    211      *
    212      * @param filePath the path to the properties file to merge.
    213      * @throws FileNotFoundException is thrown when the filePath points to a
    214      * non-existent file
    215      * @throws IOException is thrown when there is an exception loading/merging
    216      * the properties
    217      */
    218     public static void mergeProperties(File filePath) throws FileNotFoundException, IOException {
    219         final FileInputStream fis = new FileInputStream(filePath);
    220         mergeProperties(fis);
    221     }
    222
    223     /**
    224      * Merges a new properties file into the current properties. This method
    225      * allows for the loading of a user provided properties file.<br/><br/>
    226      * Note: even if using this method - system properties will be loaded before
    227      * properties loaded from files.
    228      *
    229      * @param filePath the path to the properties file to merge.
    230      * @throws FileNotFoundException is thrown when the filePath points to a
    231      * non-existent file
    232      * @throws IOException is thrown when there is an exception loading/merging
    233      * the properties
    234      */
    235     public static void mergeProperties(String filePath) throws FileNotFoundException, IOException {
    236         final FileInputStream fis = new FileInputStream(filePath);
    237         mergeProperties(fis);
    238     }
    239
    240     /**
    241      * Merges a new properties file into the current properties. This method
    242      * allows for the loading of a user provided properties file.<br/><br/>
    243      * Note: even if using this method - system properties will be loaded before
    244      * properties loaded from files.
    245      *
    246      * @param stream an Input Stream pointing at a properties file to merge
    247      * @throws IOException is thrown when there is an exception loading/merging
    248      * the properties
    249      */
    250     public static void mergeProperties(InputStream stream) throws IOException {
    251         INSTANCE.props.load(stream);
    252     }
    253
    254     /**
    255      * Returns a value from the properties file as a File object. If the value
    256      * was specified as a system property or passed in via the -Dprop=value
    257      * argument - this method will return the value from the system properties
    258      * before the values in the contained configuration file.
    259      *
    260      * This method will also replace a leading "[JAR]\" sequence with the path
    261      * to the folder containing the JAR file containing this class.
    262      *
    263      * @param key the key to lookup within the properties file
    264      * @return the property from the properties file converted to a File object
    265      */
    266     public static File getFile(String key) {
    267         final String file = getString(key);
    268         final String baseDir = getString(Settings.KEYS.DATA_DIRECTORY);
    269         if (baseDir != null) {
    270             if (baseDir.startsWith("[JAR]/")) {
    271                 final File jarPath = getJarPath();
    272                 final File newBase = new File(jarPath, baseDir.substring(6));
    273                 if (Settings.KEYS.DATA_DIRECTORY.equals(key)) {
    274                     return newBase;
    275                 }
    276                 return new File(newBase, file);
    277             }
    278             if (Settings.KEYS.DATA_DIRECTORY.equals(key)) {
    279                 return new File(baseDir);
    280             }
    281             return new File(baseDir, file);
    282         }
    283         return new File(file);
    284     }
    285
    286     /**
    287      * Attempts to retrieve the folder containing the Jar file containing the
    288      * Settings class.
    289      *
    290      * @return a File object
    291      */
    292     private static File getJarPath() {
    293         final String jarPath = Settings.class.getProtectionDomain().getCodeSource().getLocation().getPath();
    294         String decodedPath = ".";
    295         try {
    296             decodedPath = URLDecoder.decode(jarPath, "UTF-8");
    297         } catch (UnsupportedEncodingException ex) {
    298             Logger.getLogger(Settings.class.getName()).log(Level.FINEST, null, ex);
    299         }
    300
    301         final File path = new File(decodedPath);
    302         if (path.getName().toLowerCase().endsWith(".jar")) {
    303             return path.getParentFile();
    304         } else {
    305             return new File(".");
    306         }
    307     }
    308
    309     /**
    310      * Returns a value from the properties file. If the value was specified as a
    311      * system property or passed in via the -Dprop=value argument - this method
    312      * will return the value from the system properties before the values in the
    313      * contained configuration file.
    314      *
    315      * @param key the key to lookup within the properties file
    316      * @param defaultValue the default value for the requested property
    317      * @return the property from the properties file
    318      */
    319     public static String getString(String key, String defaultValue) {
    320         final String str = System.getProperty(key, INSTANCE.props.getProperty(key, defaultValue));
    321         return str;
    322     }
    323
    324     /**
    325      * Returns the temporary directory.
    326      *
    327      * @return the temporary directory
    328      */
    329     public static File getTempDirectory() {
    330         return new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")));
    331     }
    332
    333     /**
    334      * Returns a value from the properties file. If the value was specified as a
    335      * system property or passed in via the -Dprop=value argument - this method
    336      * will return the value from the system properties before the values in the
    337      * contained configuration file.
    338      *
    339      * @param key the key to lookup within the properties file
    340      * @return the property from the properties file
    341      */
    342     public static String getString(String key) {
    343         return System.getProperty(key, INSTANCE.props.getProperty(key));
    344     }
    345
    346     /**
    347      * Removes a property from the local properties collection. This is mainly
    348      * used in test cases.
    349      *
    350      * @param key the property key to remove
    351      */
    352     public static void removeProperty(String key) {
    353         INSTANCE.props.remove(key);
    354     }
    355
    356     /**
    357      * Returns an int value from the properties file. If the value was specified
    358      * as a system property or passed in via the -Dprop=value argument - this
    359      * method will return the value from the system properties before the values
    360      * in the contained configuration file.
    361      *
    362      * @param key the key to lookup within the properties file
    363      * @return the property from the properties file
    364      * @throws InvalidSettingException is thrown if there is an error retrieving
    365      * the setting
    366      */
    367     public static int getInt(String key) throws InvalidSettingException {
    368         int value;
    369         try {
    370             value = Integer.parseInt(Settings.getString(key));
    371         } catch (NumberFormatException ex) {
    372             throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
    373         }
    374         return value;
    375     }
    376
    377     /**
    378      * Returns an int value from the properties file. If the value was specified
    379      * as a system property or passed in via the -Dprop=value argument - this
    380      * method will return the value from the system properties before the values
    381      * in the contained configuration file.
    382      *
    383      * @param key the key to lookup within the properties file
    384      * @param defaultValue the default value to return
    385      * @return the property from the properties file or the defaultValue if the
    386      * property does not exist or cannot be converted to an integer
    387      */
    388     public static int getInt(String key, int defaultValue) {
    389         int value;
    390         try {
    391             value = Integer.parseInt(Settings.getString(key));
    392         } catch (NumberFormatException ex) {
    393             final String msg = String.format("Could not convert property '%s' to an int.", key);
    394             Logger.getLogger(Settings.class.getName()).log(Level.FINEST, msg, ex);
    395             value = defaultValue;
    396         }
    397         return value;
    398     }
    399
    400     /**
    401      * Returns a long value from the properties file. If the value was specified
    402      * as a system property or passed in via the -Dprop=value argument - this
    403      * method will return the value from the system properties before the values
    404      * in the contained configuration file.
    405      *
    406      * @param key the key to lookup within the properties file
    407      * @return the property from the properties file
    408      * @throws InvalidSettingException is thrown if there is an error retrieving
    409      * the setting
    410      */
    411     public static long getLong(String key) throws InvalidSettingException {
    412         long value;
    413         try {
    414             value = Long.parseLong(Settings.getString(key));
    415         } catch (NumberFormatException ex) {
    416             throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
    417         }
    418         return value;
    419     }
    420
    421     /**
    422      * Returns a boolean value from the properties file. If the value was
    423      * specified as a system property or passed in via the
    424      * <code>-Dprop=value</code> argument this method will return the value from
    425      * the system properties before the values in the contained configuration
    426      * file.
    427      *
    428      * @param key the key to lookup within the properties file
    429      * @return the property from the properties file
    430      * @throws InvalidSettingException is thrown if there is an error retrieving
    431      * the setting
    432      */
    433     public static boolean getBoolean(String key) throws InvalidSettingException {
    434         boolean value;
    435         try {
    436             value = Boolean.parseBoolean(Settings.getString(key));
    437         } catch (NumberFormatException ex) {
    438             throw new InvalidSettingException("Could not convert property '" + key + "' to an int.", ex);
    439         }
    440         return value;
    441     }
    442 }