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) 2013 Jeremy Long. All Rights Reserved.
    18   */
    19  package org.owasp.dependencycheck.data.update;
    20
    21  import java.io.File;
    22  import java.io.FileInputStream;
    23  import java.io.FileNotFoundException;
    24  import java.io.FileOutputStream;
    25  import java.io.IOException;
    26  import java.io.InputStream;
    27  import java.io.OutputStream;
    28  import java.io.OutputStreamWriter;
    29  import java.util.Properties;
    30  import java.util.logging.Level;
    31  import java.util.logging.Logger;
    32  import org.owasp.dependencycheck.data.UpdateException;
    33  import org.owasp.dependencycheck.data.nvdcve.CveDB;
    34  import org.owasp.dependencycheck.utils.Settings;
    35
    36  /**
    37   *
    38   * @author Jeremy Long (jeremy.long@owasp.org)
    39   */
    40  public class DataStoreMetaInfo {
    41
    42      /**
    43       * Batch key word, used as key to store information about batch mode.
    44       */
    45      public static final String BATCH = "batch";
    46      /**
    47       * Modified key word, used as a key to store information about the modified
    48       * file (i.e. the containing the last 8 days of updates)..
    49       */
    50      public static final String MODIFIED = "modified";
    51      /**
    52       * The name of the properties file containing the timestamp of the last
    53       * update.
    54       */
    55      private static final String UPDATE_PROPERTIES_FILE = "data.properties";
    56      /**
    57       * The properties file key for the last updated field - used to store the
    58       * last updated time of the Modified NVD CVE xml file.
    59       */
    60      public static final String LAST_UPDATED = "lastupdated.modified";
    61      /**
    62       * Stores the last updated time for each of the NVD CVE files. These
    63       * timestamps should be updated if we process the modified file within 7
    64       * days of the last update.
    65       */
    66      public static final String LAST_UPDATED_BASE = "lastupdated.";
    67      /**
    68       * A collection of properties about the data.
    69       */
    70      private Properties properties = new Properties();
    71      /**
    72       * Indicates whether or not the updates are using a batch update mode or
    73       * not.
    74       */
    75      private boolean batchUpdateMode;
    76
    77      /**
    78       * Get the value of batchUpdateMode.
    79       *
    80       * @return the value of batchUpdateMode
    81       */
    82      protected boolean isBatchUpdateMode() {
    83          return batchUpdateMode;
    84      }
    85
    86      /**
    87       * Set the value of batchUpdateMode.
    88       *
    89       * @param batchUpdateMode new value of batchUpdateMode
    90       */
    91      protected void setBatchUpdateMode(boolean batchUpdateMode) {
    92          this.batchUpdateMode = batchUpdateMode;
    93      }
    94
    95      /**
    96       * Constructs a new data properties object.
    97       */
    98      public DataStoreMetaInfo() {
    99          batchUpdateMode = !Settings.getString(Settings.KEYS.BATCH_UPDATE_URL, "").isEmpty();
    100         loadProperties();
    101     }
    102
    103     /**
    104      * Loads the data's meta properties.
    105      */
    106     private void loadProperties() {
    107         final File file = getPropertiesFile();
    108         if (file.exists()) {
    109             InputStream is = null;
    110             try {
    111                 is = new FileInputStream(file);
    112             } catch (FileNotFoundException ignore) {
    113                 //we will never get here as we check for existence above.
    114                 Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINEST, null, ignore);
    115             }
    116             try {
    117                 properties.load(is);
    118             } catch (IOException ex) {
    119                 final String msg = String.format("Unable to load properties file '%s'", file.getPath());
    120                 Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.WARNING, msg);
    121                 Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, null, ex);
    122             } finally {
    123                 if (is != null) {
    124                     try {
    125                         is.close();
    126                     } catch (IOException ex) {
    127                         final String msg = String.format("Unable to close properties file '%s'", file.getPath());
    128                         Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.WARNING, msg);
    129                         Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, null, ex);
    130                     }
    131                 }
    132             }
    133         }
    134     }
    135
    136     /**
    137      * Returns whether or not any properties are set.
    138      *
    139      * @return whether or not any properties are set
    140      */
    141     public boolean isEmpty() {
    142         return properties.isEmpty();
    143     }
    144
    145     /**
    146      * Writes a properties file containing the last updated date to the
    147      * VULNERABLE_CPE directory.
    148      *
    149      * @param updatedValue the updated nvdcve entry
    150      * @throws UpdateException is thrown if there is an update exception
    151      */
    152     public void save(NvdCveInfo updatedValue) throws UpdateException {
    153         if (updatedValue == null) {
    154             return;
    155         }
    156         final File cveProp = getPropertiesFile();
    157         final Properties prop = new Properties();
    158         if (cveProp.exists()) {
    159             FileInputStream in = null;
    160             try {
    161                 in = new FileInputStream(cveProp);
    162                 prop.load(in);
    163             } catch (Exception ignoreMe) {
    164                 Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINEST, null, ignoreMe);
    165             } finally {
    166                 if (in != null) {
    167                     try {
    168                         in.close();
    169                     } catch (Exception ignoreMeToo) {
    170                         Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINEST, null, ignoreMeToo);
    171                     }
    172                 }
    173             }
    174         }
    175         prop.put("version", CveDB.DB_SCHEMA_VERSION);
    176         prop.put(LAST_UPDATED_BASE + updatedValue.getId(), String.valueOf(updatedValue.getTimestamp()));
    177
    178         OutputStream os = null;
    179         OutputStreamWriter out = null;
    180         try {
    181             os = new FileOutputStream(cveProp);
    182             out = new OutputStreamWriter(os, "UTF-8");
    183             prop.store(out, "Meta data about data and data sources used by dependency-check");
    184         } catch (FileNotFoundException ex) {
    185             Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, null, ex);
    186             throw new UpdateException("Unable to find last updated properties file.", ex);
    187         } catch (IOException ex) {
    188             Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, null, ex);
    189             throw new UpdateException("Unable to update last updated properties file.", ex);
    190         } finally {
    191             if (out != null) {
    192                 try {
    193                     out.close();
    194                 } catch (IOException ex) {
    195                     Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINEST, null, ex);
    196                 }
    197             }
    198             if (os != null) {
    199                 try {
    200                     os.close();
    201                 } catch (IOException ex) {
    202                     Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINEST, null, ex);
    203                 }
    204             }
    205         }
    206     }
    207
    208     /**
    209      * Returns the property value for the given key. If the key is not contained
    210      * in the underlying properties null is returned.
    211      *
    212      * @param key the property key
    213      * @return the value of the property
    214      */
    215     public String getProperty(String key) {
    216         return properties.getProperty(key);
    217     }
    218
    219     /**
    220      * Returns the property value for the given key. If the key is not contained
    221      * in the underlying properties the default value is returned.
    222      *
    223      * @param key the property key
    224      * @param defaultValue the default value
    225      * @return the value of the property
    226      */
    227     public String getProperty(String key, String defaultValue) {
    228         return properties.getProperty(key, defaultValue);
    229     }
    230
    231     /**
    232      * Retrieves the properties file.
    233      *
    234      * @return the properties file
    235      */
    236     public static File getPropertiesFile() {
    237         final File dataDirectory = Settings.getFile(Settings.KEYS.DATA_DIRECTORY);
    238         final File file = new File(dataDirectory, UPDATE_PROPERTIES_FILE);
    239         return file;
    240     }
    241 }