From bb20129f0e702cc1d2bf4377087097aa295b98b5 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 17 Dec 2017 07:36:23 -0500 Subject: [PATCH] updated lock file cleanup to be useable by other build plugins --- .../utils/H2DBCleanupHook.java | 54 ++++++++++++++++--- .../owasp/dependencycheck/utils/H2DBLock.java | 18 ++++--- .../utils/H2DBShutdownHook.java | 39 ++++++++++++++ .../utils/H2DBShutdownHookFactory.java | 51 ++++++++++++++++++ .../main/resources/dependencycheck.properties | 2 + .../test/resources/dependencycheck.properties | 3 ++ .../maven/BaseDependencyCheckMojo.java | 2 +- .../owasp/dependencycheck/utils/Settings.java | 5 ++ 8 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHook.java create mode 100644 dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHookFactory.java diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBCleanupHook.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBCleanupHook.java index 5761a1f76..3ede33dae 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBCleanupHook.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBCleanupHook.java @@ -1,34 +1,74 @@ /* - * Copyright 2017 OWASP. + * This file is part of dependency-check-core. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. */ package org.owasp.dependencycheck.utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** + * A cleanup hook that will register with the JVM to remove the H@DBLock file + * during an unexpected shutdown. * - * @author jeremy + * @author Jeremy Long */ -public class H2DBCleanupHook extends Thread { +public class H2DBCleanupHook extends H2DBShutdownHook { - private final H2DBLock lock; + /** + * A reference to the lock file. + */ + private H2DBLock lock; - public H2DBCleanupHook(H2DBLock lock) { + /** + * The logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(H2DBShutdownHookFactory.class); + + /** + * Add the shutdown hook. + * + * @param lock the lock object + */ + @Override + public void add(H2DBLock lock) { this.lock = lock; + Runtime.getRuntime().addShutdownHook(this); } + /** + * Removes the shutdown hook. + */ + @Override + public void remove() { + try { + Runtime.getRuntime().removeShutdownHook(this); + } catch (IllegalStateException ex) { + LOGGER.trace("ignore as we are likely shutting down", ex); + } + } + + /** + * Releases the custom h2 lock file used by dependency-check. + */ @Override public void run() { - lock.release(); + if (lock != null) { + lock.release(); + lock = null; + } } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java index 608b00914..b4fb2a5fb 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBLock.java @@ -30,6 +30,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** + * The H2 DB lock file implementation; creates a custom lock file so that only a + * single instance of dependency-check can update the embedded h2 database. * * @author Jeremy Long */ @@ -69,7 +71,10 @@ public class H2DBLock { */ private final String magic; - private H2DBCleanupHook hook = null; + /** + * The shutdown hook used to remove the lock file in case of an unexpected shutdown. + */ + private H2DBShutdownHook hook = null; /** * Constructs a new H2DB Lock object with the configured settings. @@ -229,18 +234,15 @@ public class H2DBLock { private void addShutdownHook() { if (hook == null) { - hook = new H2DBCleanupHook(this); - Runtime.getRuntime().addShutdownHook(hook); + hook = H2DBShutdownHookFactory.getHook(settings); + hook.add(this); + } } private void removeShutdownHook() { if (hook != null) { - try { - Runtime.getRuntime().removeShutdownHook(hook); - } catch (IllegalStateException ex) { - LOGGER.trace("ignore as we are likely shutting down", ex); - } + hook.remove(); hook = null; } } diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHook.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHook.java new file mode 100644 index 000000000..14a18b72d --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHook.java @@ -0,0 +1,39 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.utils; + +/** + * Definition of the shutdown hook used during the unexpected shutdown during + * the update process of the H2 DB. + * + * @author Jeremy Long + */ +public abstract class H2DBShutdownHook extends Thread { + + /** + * Adds the shutdown hook. + * + * @param lock the H2DB Lock reference + */ + public abstract void add(H2DBLock lock); + + /** + * Removes the shutdown hook. + */ + public abstract void remove(); +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHookFactory.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHookFactory.java new file mode 100644 index 000000000..3c3d8c7c9 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/utils/H2DBShutdownHookFactory.java @@ -0,0 +1,51 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2017 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Simple factory to instantiate the H2DB Shutdown Hook. + * + * @author Jeremy Long + */ +public final class H2DBShutdownHookFactory { + + /** + * The logger. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(H2DBShutdownHookFactory.class); + + /** + * Creates a new H2DB Shutdown Hook. + * + * @param settings the configured settings + * @return the H2DB Shutdown Hook + */ + public static H2DBShutdownHook getHook(Settings settings) { + try { + String className = settings.getString(Settings.KEYS.H2DB_SHUTDOWN_HOOK, "org.owasp.dependencycheck.utils.H2DBCleanupHook"); + Class type = Class.forName(className); + return (H2DBShutdownHook) type.newInstance(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) { + LOGGER.debug("Failed to instantiate {}, using default shutdown hook instead", ex); + return new H2DBCleanupHook(); + } + } +} diff --git a/dependency-check-core/src/main/resources/dependencycheck.properties b/dependency-check-core/src/main/resources/dependencycheck.properties index 761d09984..d3dbe7bdd 100644 --- a/dependency-check-core/src/main/resources/dependencycheck.properties +++ b/dependency-check-core/src/main/resources/dependencycheck.properties @@ -41,6 +41,8 @@ data.password=DC-Pass1337! data.driver_name=org.h2.Driver data.driver_path= +# the class name of the H2 database shutdown hook +data.h2.shutdownhook=org.owasp.dependencycheck.utils.H2DBCleanupHook proxy.disableSchemas=true # the number of days that the modified nvd cve data holds data for. We don't need diff --git a/dependency-check-core/src/test/resources/dependencycheck.properties b/dependency-check-core/src/test/resources/dependencycheck.properties index eec27880c..1d6e11195 100644 --- a/dependency-check-core/src/test/resources/dependencycheck.properties +++ b/dependency-check-core/src/test/resources/dependencycheck.properties @@ -36,6 +36,9 @@ data.password=DC-Pass1337! data.driver_name=org.h2.Driver data.driver_path= +# the class name of the H2 database shutdown hook +data.h2.shutdownhook=org.owasp.dependencycheck.utils.H2DBCleanupHook + proxy.disableSchemas=true # the number of days that the modified nvd cve data holds data for. We don't need # to update the other files if we are within this timespan. Per NIST this file diff --git a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java index d77ce3b13..1e9e894c2 100644 --- a/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java +++ b/dependency-check-maven/src/main/java/org/owasp/dependencycheck/maven/BaseDependencyCheckMojo.java @@ -1106,7 +1106,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma mojoProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE); settings.mergeProperties(mojoProperties); } catch (IOException ex) { - getLog().warn("Unable to load the dependency-check ant task.properties file."); + getLog().warn("Unable to load the dependency-check maven mojo.properties file."); if (getLog().isDebugEnabled()) { getLog().debug("", ex); } diff --git a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java index 2ba4f1feb..56fca5188 100644 --- a/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java +++ b/dependency-check-utils/src/main/java/org/owasp/dependencycheck/utils/Settings.java @@ -456,6 +456,10 @@ public final class Settings { * Size of database batch inserts */ public static final String MAX_BATCH_SIZE = "database.batchinsert.maxsize"; + /** + * The key that specifies the class name of the H2 database shutdown hook. + */ + public static String H2DB_SHUTDOWN_HOOK = "data.h2.shutdownhook"; /** * private constructor because this is a "utility" class containing @@ -958,6 +962,7 @@ public final class Settings { } if (connStr.contains("%s")) { final File directory = getDataDirectory(); + LOGGER.debug("Data directory: {}", directory); String fileName = null; if (dbFileNameKey != null) { fileName = getString(dbFileNameKey);