refactoring update tasks

Former-commit-id: d9b72f31b3df06106414bb3de925311f9acfc0d5
This commit is contained in:
Jeremy Long
2013-10-08 15:19:22 -04:00
parent f4e2220684
commit 5d5940a343
10 changed files with 292 additions and 98 deletions

View File

@@ -21,7 +21,6 @@ package org.owasp.dependencycheck.data.update;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import org.owasp.dependencycheck.data.CachedWebDataSource;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -47,25 +46,64 @@ import org.xml.sax.SAXException;
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public abstract class AbstractUpdate { public abstract class AbstractUpdateTask implements UpdateTask {
/**
* Initializes the AbstractUpdateTask.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if the configuration contains a
* malformed url
* @throws DownloadFailedException thrown if the timestamp on a file cannot
* be checked
* @throws UpdateException thrown if the update fails
*/
public AbstractUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
this.properties = properties;
this.updateable = updatesNeeded();
}
/**
* A collection of updateable NVD CVE items.
*/
private Updateable updateable; private Updateable updateable;
/** /**
* Utility to read and write meta-data about the data. * Utility to read and write meta-data about the data.
*/ */
protected DataStoreMetaInfo properties = null; private DataStoreMetaInfo properties = null;
/**
* Returns the data store properties.
*
* @return the data store properties
*/
protected DataStoreMetaInfo getProperties() {
return properties;
}
/** /**
* Reference to the Cve Database. * Reference to the Cve Database.
*/ */
protected CveDB cveDB = null; private CveDB cveDB = null;
/**
* Returns the CveDB.
*
* @return the CveDB
*/
protected CveDB getCveDB() {
return cveDB;
}
/** /**
* Reference to the Cpe Index. * Reference to the Cpe Index.
*/ */
protected CpeIndexWriter cpeIndex = null; private CpeIndexWriter cpeIndex = null;
public AbstractUpdate() throws MalformedURLException, DownloadFailedException, UpdateException { /**
this.properties = new DataStoreMetaInfo(); * Returns the CpeIndex.
this.updateable = updatesNeeded(); *
* @return the CpeIndex
*/
protected CpeIndexWriter getCpeIndex() {
return cpeIndex;
} }
/** /**
@@ -82,7 +120,7 @@ public abstract class AbstractUpdate {
* *
* @return an Updateable object containing the NVD CVE entries * @return an Updateable object containing the NVD CVE entries
*/ */
public Updateable getUpdateable() { protected Updateable getUpdateable() {
return updateable; return updateable;
} }
@@ -113,7 +151,7 @@ public abstract class AbstractUpdate {
private boolean deleteAndRecreate = false; private boolean deleteAndRecreate = false;
/** /**
* Get the value of deleteAndRecreate * Get the value of deleteAndRecreate.
* *
* @return the value of deleteAndRecreate * @return the value of deleteAndRecreate
*/ */
@@ -122,11 +160,11 @@ public abstract class AbstractUpdate {
} }
/** /**
* Set the value of deleteAndRecreate * Set the value of deleteAndRecreate.
* *
* @param deleteAndRecreate new value of deleteAndRecreate * @param deleteAndRecreate new value of deleteAndRecreate
*/ */
public void setDeleteAndRecreate(boolean deleteAndRecreate) { protected void setDeleteAndRecreate(boolean deleteAndRecreate) {
this.deleteAndRecreate = deleteAndRecreate; this.deleteAndRecreate = deleteAndRecreate;
} }
@@ -158,14 +196,14 @@ public abstract class AbstractUpdate {
try { try {
cveDB.close(); cveDB.close();
} catch (Exception ignore) { } catch (Exception ignore) {
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore);
} }
} }
if (cpeIndex != null) { if (cpeIndex != null) {
try { try {
cpeIndex.close(); cpeIndex.close();
} catch (Exception ignore) { } catch (Exception ignore) {
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINEST, "Error closing the cpeIndex", ignore); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cpeIndex", ignore);
} }
} }
} }
@@ -184,19 +222,19 @@ public abstract class AbstractUpdate {
cpeIndex.open(); cpeIndex.open();
} catch (IOException ex) { } catch (IOException ex) {
closeDataStores(); closeDataStores();
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINE, "IO Error opening databases", ex); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "IO Error opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details."); throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (SQLException ex) { } catch (SQLException ex) {
closeDataStores(); closeDataStores();
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINE, "SQL Exception opening databases", ex); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "SQL Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details."); throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (DatabaseException ex) { } catch (DatabaseException ex) {
closeDataStores(); closeDataStores();
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINE, "Database Exception opening databases", ex); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Database Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details."); throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
closeDataStores(); closeDataStores();
Logger.getLogger(AbstractUpdate.class.getName()).log(Level.FINE, "Class not found exception opening databases", ex); Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Class not found exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details."); throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} }
} }

View File

@@ -43,10 +43,20 @@ import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public class BatchUpdate extends AbstractUpdate { public class BatchUpdateTask extends AbstractUpdateTask {
public BatchUpdate() throws MalformedURLException, DownloadFailedException, UpdateException { /**
super(); * Constructs a new BatchUpdateTask.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public BatchUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
super(properties);
} }
/** /**
* A flag indicating whether or not the batch update should be performed. * A flag indicating whether or not the batch update should be performed.
@@ -80,7 +90,7 @@ public class BatchUpdate extends AbstractUpdate {
*/ */
@Override @Override
public void update() throws UpdateException { public void update() throws UpdateException {
if (properties.isBatchUpdateMode() && doBatchUpdate) { if (getProperties().isBatchUpdateMode() && doBatchUpdate) {
final String batchSrc = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL); final String batchSrc = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL);
File tmp = null; File tmp = null;
try { try {
@@ -134,17 +144,17 @@ public class BatchUpdate extends AbstractUpdate {
updates = retrieveCurrentTimestampsFromWeb(); updates = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) { } catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(BatchUpdate.class.getName()).log(Level.FINE, msg, ex); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex); throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) { } catch (InvalidSettingException ex) {
Logger.getLogger(BatchUpdate.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex); throw new DownloadFailedException("Invalid settings", ex);
} }
if (updates == null) { if (updates == null) {
throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
} }
final DataStoreMetaInfo properties = getProperties();
if (!properties.isEmpty()) { if (!properties.isEmpty()) {
try { try {
boolean deleteAndRecreate = false; boolean deleteAndRecreate = false;
@@ -178,8 +188,8 @@ public class BatchUpdate extends AbstractUpdate {
deleteExistingData(); deleteExistingData();
} catch (IOException ex) { } catch (IOException ex) {
final String msg = "Unable to delete existing data"; final String msg = "Unable to delete existing data";
Logger.getLogger(BatchUpdate.class.getName()).log(Level.WARNING, msg); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(BatchUpdate.class.getName()).log(Level.FINE, null, ex); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, null, ex);
} }
return updates; return updates;
} }
@@ -214,7 +224,7 @@ public class BatchUpdate extends AbstractUpdate {
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated", final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DataStoreMetaInfo.LAST_UPDATED_BASE, String.valueOf(i)); DataStoreMetaInfo.LAST_UPDATED_BASE, String.valueOf(i));
Logger.getLogger(BatchUpdate.class.getName()).log(Level.FINE, msg, ex); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, msg, ex);
} }
if (currentTimestamp == cve.getTimestamp()) { if (currentTimestamp == cve.getTimestamp()) {
cve.setNeedsUpdate(false); //they default to true. cve.setNeedsUpdate(false); //they default to true.
@@ -223,8 +233,8 @@ public class BatchUpdate extends AbstractUpdate {
} }
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file."; final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger.getLogger(BatchUpdate.class.getName()).log(Level.WARNING, msg); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(BatchUpdate.class.getName()).log(Level.FINE, null, ex); Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, null, ex);
setDoBatchUpdate(properties.isBatchUpdateMode()); setDoBatchUpdate(properties.isBatchUpdateMode());
} }
} }
@@ -245,11 +255,11 @@ public class BatchUpdate extends AbstractUpdate {
*/ */
private Updateable retrieveCurrentTimestampsFromWeb() private Updateable retrieveCurrentTimestampsFromWeb()
throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException { throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
Updateable updates = new Updateable(); final Updateable updates = new Updateable();
updates.add(BATCH, Settings.getString(Settings.KEYS.BATCH_UPDATE_URL), updates.add(BATCH, Settings.getString(Settings.KEYS.BATCH_UPDATE_URL),
null, false); null, false);
String url = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL, ""); final String url = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL, "");
if (!url.isEmpty()) { if (!url.isEmpty()) {
final NvdCveInfo item = new NvdCveInfo(); final NvdCveInfo item = new NvdCveInfo();
updates.add(MODIFIED, url, updates.add(MODIFIED, url,

View File

@@ -39,11 +39,6 @@ import org.owasp.dependencycheck.utils.Settings;
*/ */
public class DatabaseUpdater implements CachedWebDataSource { public class DatabaseUpdater implements CachedWebDataSource {
/**
* Utility to read and write meta-data about the data.
*/
protected DataStoreMetaInfo properties = null;
/** /**
* <p>Downloads the latest NVD CVE XML file from the web and imports it into * <p>Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p> * the current CVE Database.</p>
@@ -53,9 +48,7 @@ public class DatabaseUpdater implements CachedWebDataSource {
*/ */
@Override @Override
public void update() throws UpdateException { public void update() throws UpdateException {
properties = new DataStoreMetaInfo(); final File dataDir = Settings.getFile(Settings.KEYS.DATA_DIRECTORY);
AbstractUpdate store = null;
File dataDir = Settings.getFile(Settings.KEYS.DATA_DIRECTORY);
DirectorySpinLock lock = null; DirectorySpinLock lock = null;
try { try {
lock = new DirectorySpinLock(dataDir); lock = new DirectorySpinLock(dataDir);
@@ -67,15 +60,13 @@ public class DatabaseUpdater implements CachedWebDataSource {
try { try {
lock.obtainSharedLock(); lock.obtainSharedLock();
if (properties.isBatchUpdateMode()) { final UpdateTask task = UpdateTaskFactory.getUpdateTask();
store = new BatchUpdate();
} else {
store = new StandardUpdate(); if (task.isUpdateNeeded()) {
}
if (store.isUpdateNeeded()) {
lock.release(); lock.release();
lock.obtainExclusiveLock(); lock.obtainExclusiveLock();
if (store.shouldDeleteAndRecreate()) { if (task.shouldDeleteAndRecreate()) {
try { try {
deleteExistingData(); deleteExistingData();
} catch (IOException ex) { } catch (IOException ex) {
@@ -83,7 +74,7 @@ public class DatabaseUpdater implements CachedWebDataSource {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex); Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
} }
} }
store.update(); task.update();
} }
} catch (DirectoryLockException ex) { } catch (DirectoryLockException ex) {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING, Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING,

View File

@@ -45,10 +45,20 @@ import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public class StandardUpdate extends AbstractUpdate { public class StandardUpdateTask extends AbstractUpdateTask {
public StandardUpdate() throws MalformedURLException, DownloadFailedException, UpdateException { /**
super(); * Constructs a new Standard Update Task.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public StandardUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
super(properties);
} }
/** /**
@@ -68,7 +78,7 @@ public class StandardUpdate extends AbstractUpdate {
} }
} }
if (maxUpdates > 3) { if (maxUpdates > 3) {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"NVD CVE requires several updates; this could take a couple of minutes."); "NVD CVE requires several updates; this could take a couple of minutes.");
} }
if (maxUpdates > 0) { if (maxUpdates > 0) {
@@ -79,13 +89,13 @@ public class StandardUpdate extends AbstractUpdate {
for (NvdCveInfo cve : getUpdateable()) { for (NvdCveInfo cve : getUpdateable()) {
if (cve.getNeedsUpdate()) { if (cve.getNeedsUpdate()) {
count += 1; count += 1;
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Updating NVD CVE ({0} of {1})", new Object[]{count, maxUpdates}); "Updating NVD CVE ({0} of {1})", new Object[]{count, maxUpdates});
URL url = new URL(cve.getUrl()); URL url = new URL(cve.getUrl());
File outputPath = null; File outputPath = null;
File outputPath12 = null; File outputPath12 = null;
try { try {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Downloading {0}", cve.getUrl()); "Downloading {0}", cve.getUrl());
outputPath = File.createTempFile("cve" + cve.getId() + "_", ".xml"); outputPath = File.createTempFile("cve" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath); Downloader.fetchFile(url, outputPath);
@@ -94,17 +104,16 @@ public class StandardUpdate extends AbstractUpdate {
outputPath12 = File.createTempFile("cve_1_2_" + cve.getId() + "_", ".xml"); outputPath12 = File.createTempFile("cve_1_2_" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath12); Downloader.fetchFile(url, outputPath12);
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO, Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Processing {0}", cve.getUrl()); "Processing {0}", cve.getUrl());
importXML(outputPath, outputPath12); importXML(outputPath, outputPath12);
cveDB.commit(); getCveDB().commit();
cpeIndex.commit(); getCpeIndex().commit();
getProperties().save(cve);
properties.save(cve); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
Logger.getLogger(StandardUpdate.class.getName()).log(Level.INFO,
"Completed update {0} of {1}", new Object[]{count, maxUpdates}); "Completed update {0} of {1}", new Object[]{count, maxUpdates});
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
throw new UpdateException(ex); throw new UpdateException(ex);
@@ -145,8 +154,8 @@ public class StandardUpdate extends AbstractUpdate {
} }
} }
if (maxUpdates >= 1) { //ensure the modified file date gets written if (maxUpdates >= 1) { //ensure the modified file date gets written
properties.save(getUpdateable().get(MODIFIED)); getProperties().save(getUpdateable().get(MODIFIED));
cveDB.cleanupDatabase(); getCveDB().cleanupDatabase();
} }
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
throw new UpdateException(ex); throw new UpdateException(ex);
@@ -176,17 +185,17 @@ public class StandardUpdate extends AbstractUpdate {
updates = retrieveCurrentTimestampsFromWeb(); updates = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) { } catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page"; final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, msg, ex); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex); throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) { } catch (InvalidSettingException ex) {
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex); throw new DownloadFailedException("Invalid settings", ex);
} }
if (updates == null) { if (updates == null) {
throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data"); throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
} }
final DataStoreMetaInfo properties = getProperties();
if (!properties.isEmpty()) { if (!properties.isEmpty()) {
try { try {
float version; float version;
@@ -235,7 +244,7 @@ public class StandardUpdate extends AbstractUpdate {
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated", final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DataStoreMetaInfo.LAST_UPDATED_BASE, entry.getId()); DataStoreMetaInfo.LAST_UPDATED_BASE, entry.getId());
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, msg, ex); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, msg, ex);
} }
if (currentTimestamp == entry.getTimestamp()) { if (currentTimestamp == entry.getTimestamp()) {
entry.setNeedsUpdate(false); entry.setNeedsUpdate(false);
@@ -245,8 +254,8 @@ public class StandardUpdate extends AbstractUpdate {
} }
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file."; final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger.getLogger(StandardUpdate.class.getName()).log(Level.WARNING, msg); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(StandardUpdate.class.getName()).log(Level.FINE, null, ex); Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, null, ex);
} }
} }
return updates; return updates;

View File

@@ -0,0 +1,51 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.UpdateException;
/**
* An interface defining an update task.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public interface UpdateTask {
/**
* <p>Updates the data store to the latest version.</p>
*
* @throws UpdateException is thrown if there is an error updating the
* database
*/
void update() throws UpdateException;
/**
* Get the value of deleteAndRecreate.
*
* @return the value of deleteAndRecreate
*/
boolean shouldDeleteAndRecreate();
/**
* Gets whether or not an update is needed.
*
* @return true or false depending on whether an update is needed
*/
boolean isUpdateNeeded();
}

View File

@@ -0,0 +1,60 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.net.MalformedURLException;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
/**
* An UpdateTask Factory that instantiates the correct UpdateTask based on the
* given configuration.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class UpdateTaskFactory {
/**
* private constructor for a utility class.
*/
private UpdateTaskFactory() {
//empty contrusctor for utility class
}
/**
* Constructs the appropriate update task based on configuration.
*
* @return an UpdateTask
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public static UpdateTask getUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
final UpdateTask task;
final DataStoreMetaInfo properties = new DataStoreMetaInfo();
if (properties.isBatchUpdateMode()) {
task = new BatchUpdateTask(properties);
} else {
task = new StandardUpdateTask(properties);
}
return task;
}
}

View File

@@ -1,6 +1,20 @@
/* /*
* To change this template, choose Tools | Templates * This file is part of dependency-check-core.
* and open the template in the editor. *
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core 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 General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/ */
package org.owasp.dependencycheck.data.update; package org.owasp.dependencycheck.data.update;
@@ -24,7 +38,7 @@ public class Updateable implements java.lang.Iterable<NvdCveInfo>, Iterator<NvdC
/** /**
* A collection of sources of data. * A collection of sources of data.
*/ */
Map<String, NvdCveInfo> collection = new TreeMap<String, NvdCveInfo>(); private Map<String, NvdCveInfo> collection = new TreeMap<String, NvdCveInfo>();
/** /**
* Gets whether or not an update is needed. * Gets whether or not an update is needed.
@@ -66,7 +80,7 @@ public class Updateable implements java.lang.Iterable<NvdCveInfo>, Iterator<NvdC
* @throws DownloadFailedException thrown if the download fails. * @throws DownloadFailedException thrown if the download fails.
*/ */
public void add(String id, String url, String oldUrl, boolean needsUpdate) throws MalformedURLException, DownloadFailedException { public void add(String id, String url, String oldUrl, boolean needsUpdate) throws MalformedURLException, DownloadFailedException {
NvdCveInfo item = new NvdCveInfo(); final NvdCveInfo item = new NvdCveInfo();
item.setNeedsUpdate(needsUpdate); //the others default to true, to make life easier later this should default to false. item.setNeedsUpdate(needsUpdate); //the others default to true, to make life easier later this should default to false.
item.setId(id); item.setId(id);
item.setUrl(url); item.setUrl(url);
@@ -94,7 +108,7 @@ public class Updateable implements java.lang.Iterable<NvdCveInfo>, Iterator<NvdC
/** /**
* An internal iterator used to implement iterable. * An internal iterator used to implement iterable.
*/ */
Iterator<Entry<String, NvdCveInfo>> iterableContent = null; private Iterator<Entry<String, NvdCveInfo>> iterableContent = null;
/** /**
* <p>Returns an iterator for the NvdCveInfo contained.</p> * <p>Returns an iterator for the NvdCveInfo contained.</p>

View File

@@ -38,9 +38,9 @@ import org.owasp.dependencycheck.utils.DownloadFailedException;
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public class AbstractUpdateTest { public class AbstractUpdateTaskTest {
public AbstractUpdateTest() { public AbstractUpdateTaskTest() {
} }
@BeforeClass @BeforeClass
@@ -59,25 +59,31 @@ public class AbstractUpdateTest {
public void tearDown() { public void tearDown() {
} }
public AbstractUpdateTask getAbstractUpdateImpl() throws Exception {
DataStoreMetaInfo props = new DataStoreMetaInfo();
AbstractUpdateTask instance = new AbstractUpdateImpl(props);
return instance;
}
/** /**
* Test of setDeleteAndRecreate method, of class AbstractUpdate. * Test of setDeleteAndRecreate method, of class AbstractUpdateTask.
*/ */
@Test @Test
public void testSetDeleteAndRecreate() throws Exception { public void testSetDeleteAndRecreate() throws Exception {
boolean deleteAndRecreate = false; boolean deleteAndRecreate = false;
boolean expResult = false; boolean expResult = false;
AbstractUpdate instance = new AbstractUpdateImpl(); AbstractUpdateTask instance = getAbstractUpdateImpl();
instance.setDeleteAndRecreate(deleteAndRecreate); instance.setDeleteAndRecreate(deleteAndRecreate);
boolean result = instance.shouldDeleteAndRecreate(); boolean result = instance.shouldDeleteAndRecreate();
assertEquals(expResult, result); assertEquals(expResult, result);
} }
/** /**
* Test of deleteExistingData method, of class AbstractUpdate. * Test of deleteExistingData method, of class AbstractUpdateTask.
*/ */
@Test @Test
public void testDeleteExistingData() throws Exception { public void testDeleteExistingData() throws Exception {
AbstractUpdate instance = new AbstractUpdateImpl(); AbstractUpdateTask instance = getAbstractUpdateImpl();
Exception result = null; Exception result = null;
try { try {
instance.deleteExistingData(); instance.deleteExistingData();
@@ -88,17 +94,17 @@ public class AbstractUpdateTest {
} }
/** /**
* Test of openDataStores method, of class AbstractUpdate. * Test of openDataStores method, of class AbstractUpdateTask.
*/ */
@Test @Test
public void testOpenDataStores() throws Exception { public void testOpenDataStores() throws Exception {
AbstractUpdate instance = new AbstractUpdateImpl(); AbstractUpdateTask instance = getAbstractUpdateImpl();
instance.openDataStores(); instance.openDataStores();
instance.closeDataStores(); instance.closeDataStores();
} }
/** /**
* Test of withinRange method, of class AbstractUpdate. * Test of withinRange method, of class AbstractUpdateTask.
*/ */
@Test @Test
public void testWithinRange() throws Exception { public void testWithinRange() throws Exception {
@@ -107,7 +113,7 @@ public class AbstractUpdateTest {
long current = c.getTimeInMillis(); long current = c.getTimeInMillis();
long lastRun = c.getTimeInMillis() - (3 * (1000 * 60 * 60 * 24)); long lastRun = c.getTimeInMillis() - (3 * (1000 * 60 * 60 * 24));
int range = 7; // 7 days int range = 7; // 7 days
AbstractUpdate instance = new AbstractUpdateImpl(); AbstractUpdateTask instance = getAbstractUpdateImpl();
boolean expResult = true; boolean expResult = true;
boolean result = instance.withinRange(lastRun, current, range); boolean result = instance.withinRange(lastRun, current, range);
assertEquals(expResult, result); assertEquals(expResult, result);
@@ -118,10 +124,10 @@ public class AbstractUpdateTest {
assertEquals(expResult, result); assertEquals(expResult, result);
} }
public class AbstractUpdateImpl extends AbstractUpdate { public class AbstractUpdateImpl extends AbstractUpdateTask {
public AbstractUpdateImpl() throws Exception { public AbstractUpdateImpl(DataStoreMetaInfo props) throws Exception {
super(); super(props);
} }
public Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException { public Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {

View File

@@ -35,9 +35,9 @@ import org.owasp.dependencycheck.utils.Settings;
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public class BatchUpdateTest { public class BatchUpdateTaskTest {
public BatchUpdateTest() { public BatchUpdateTaskTest() {
} }
@BeforeClass @BeforeClass
@@ -86,24 +86,30 @@ public class BatchUpdateTest {
Settings.setString(Settings.KEYS.BATCH_UPDATE_URL, ""); Settings.setString(Settings.KEYS.BATCH_UPDATE_URL, "");
} }
public BatchUpdateTask getBatchUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
DataStoreMetaInfo props = new DataStoreMetaInfo();
BatchUpdateTask instance = new BatchUpdateTask(props);
return instance;
}
/** /**
* Test of setDoBatchUpdate method, of class BatchUpdate. * Test of setDoBatchUpdate method, of class BatchUpdateTask.
*/ */
@Test @Test
public void testSetDoBatchUpdate() throws DownloadFailedException, MalformedURLException, UpdateException { public void testSetDoBatchUpdate() throws DownloadFailedException, MalformedURLException, UpdateException {
boolean expected = false; boolean expected = false;
BatchUpdate instance = new BatchUpdate(); BatchUpdateTask instance = getBatchUpdateTask();
instance.setDoBatchUpdate(expected); instance.setDoBatchUpdate(expected);
boolean results = instance.isDoBatchUpdate(); boolean results = instance.isDoBatchUpdate();
assertEquals(results, expected); assertEquals(results, expected);
} }
/** /**
* Test of update method, of class BatchUpdate. * Test of update method, of class BatchUpdateTask.
*/ */
@Test @Test
public void testUpdate() throws Exception { public void testUpdate() throws Exception {
BatchUpdate instance = new BatchUpdate(); BatchUpdateTask instance = getBatchUpdateTask();
//do some setup //do some setup
instance.setDoBatchUpdate(true); instance.setDoBatchUpdate(true);

View File

@@ -18,20 +18,23 @@
*/ */
package org.owasp.dependencycheck.data.update; package org.owasp.dependencycheck.data.update;
import java.net.MalformedURLException;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
/** /**
* *
* @author Jeremy Long (jeremy.long@owasp.org) * @author Jeremy Long (jeremy.long@owasp.org)
*/ */
public class StandardUpdateIntegrationTest { public class StandardUpdateTaskIntegrationTest {
public StandardUpdateIntegrationTest() { public StandardUpdateTaskIntegrationTest() {
} }
@BeforeClass @BeforeClass
@@ -50,22 +53,28 @@ public class StandardUpdateIntegrationTest {
public void tearDown() { public void tearDown() {
} }
public StandardUpdateTask getStandardUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
DataStoreMetaInfo props = new DataStoreMetaInfo();
StandardUpdateTask instance = new StandardUpdateTask(props);
return instance;
}
/** /**
* Test of update method, of class StandardUpdate. * Test of update method, of class StandardUpdateTask.
*/ */
@Test @Test
public void testUpdate() throws Exception { public void testUpdate() throws Exception {
StandardUpdate instance = new StandardUpdate(); StandardUpdateTask instance = getStandardUpdateTask();
instance.update(); instance.update();
//TODO make this an actual test //TODO make this an actual test
} }
/** /**
* Test of updatesNeeded method, of class StandardUpdate. * Test of updatesNeeded method, of class StandardUpdateTask.
*/ */
@Test @Test
public void testUpdatesNeeded() throws Exception { public void testUpdatesNeeded() throws Exception {
StandardUpdate instance = new StandardUpdate(); StandardUpdateTask instance = getStandardUpdateTask();
Updateable result = instance.updatesNeeded(); Updateable result = instance.updatesNeeded();
assertNotNull(result); assertNotNull(result);
} }