This is an automated email from the ASF dual-hosted git repository.
ctubbsii pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo-classloaders.git
The following commit(s) were added to refs/heads/main by this push:
new 947441f Support additional checksum algorithms (#53)
947441f is described below
commit 947441fdff0624cad67d1d99644ac61fec29c690
Author: Christopher Tubbs <[email protected]>
AuthorDate: Thu Jan 29 12:18:53 2026 -0500
Support additional checksum algorithms (#53)
* Use checksum algorithms defined in the Resource to verify the checksum
* Support any algorithm supported by the JVM
* Use SHA-512 for the ContextDefinition change detection and filenames
* Use algorithm name in filenames and cache key
* Update javadocs and README
* Incorporate algorithm name normalization checks in filename tests
* Use a variety of algorithms in tests
Also:
* Remove use of non-public Accumulo APIs
* Add a checkstyle rule for the non-test code to prevent new uses of
non-public Accumulo APIs
* Use a BufferedInputStream when downloading resources for
ContextDefinition.create()
---
modules/local-caching-classloader/README.md | 32 ++--
.../lcc/LocalCachingContextClassLoaderFactory.java | 28 ++-
.../lcc/definition/ContextDefinition.java | 70 ++++++--
.../classloader/lcc/definition/Resource.java | 30 +++-
.../accumulo/classloader/lcc/util/LccUtils.java | 8 +-
.../accumulo/classloader/lcc/util/LocalStore.java | 14 +-
.../LocalCachingContextClassLoaderFactoryTest.java | 56 +++---
.../MiniAccumuloClusterClassLoaderFactoryTest.java | 8 +-
.../apache/accumulo/classloader/lcc/TestUtils.java | 7 +-
.../classloader/lcc/util/LocalStoreTest.java | 85 +++++----
pom.xml | 196 ++++++++++++---------
11 files changed, 333 insertions(+), 201 deletions(-)
diff --git a/modules/local-caching-classloader/README.md
b/modules/local-caching-classloader/README.md
index 8aecacf..a624386 100644
--- a/modules/local-caching-classloader/README.md
+++ b/modules/local-caching-classloader/README.md
@@ -62,15 +62,23 @@ Here is an example context definition file:
"resources": [
{
"location": "file:/home/user/ClassLoaderTestA/TestA.jar",
- "checksum": "a10883244d70d971ec25cbfa69b6f08f"
+ "algorithm": "MD5",
+ "checksum": "ae5e8248a9243751d60dbcaaedeb93ba"
},
{
"location": "hdfs://localhost:8020/contextB/TestB.jar",
- "checksum": "a02a3b7026528156fb782dcdecaaa097"
+ "algorithm": "SHA-256",
+ "checksum":
"ed95fe130090fd64c2caddc3e37555ada8ba49a91bfd8ec1fd5c989d340ad0e0"
},
{
"location": "http://localhost:80/TestC.jar",
- "checksum": "f464e66f6d07a41c656e8f4679509215"
+ "algorithm": "SHA3-224",
+ "checksum": "958f12ddc5acf87c2fe0ceed645327bb0c92e268acf915c4a374c14b"
+ },
+ {
+ "location": "https://localhost:80/TestD.jar",
+ "algorithm": "SHA-512/224",
+ "checksum": "f7f982521ceb8ca97662973ada9b92b86de6bbaf233f14fd47efd792"
}
]
}
@@ -116,8 +124,8 @@ and processes, so be very careful when removing old
contents to ensure that
they are no longer needed. If a resource file is deleted from the local storage
cache while a `ClassLoader` exists that references it, that `ClassLoader` may,
and probably will, stop working correctly. Similarly, files that have been
-downloaded should not be modified, because checksums are only verified on first
-download, and any modification will likely cause unexpected behavior.
+downloaded should not be modified, because any modification will likely cause
+unexpected behavior to classloaders still using the file.
* Do **NOT** use a temporary directory for the local storage cache location.
* The local storage cache location **MUST** use a filesystem that supports
@@ -125,10 +133,11 @@ download, and any modification will likely cause
unexpected behavior.
## Creating a ContextDefinition file
-Users may take advantage of the `ContextDefinition.create(int,URL[])` method to
-construct a `ContextDefinition` object, programmatically. This will calculate
-the checksums of the classpath elements. `ContextDefinition.toJson()` can be
-used to serialize the `ContextDefinition` to a `String` to store in a file.
+Users may take advantage of the `ContextDefinition.create(int,String,URL[])`
+method to construct a `ContextDefinition` object, programmatically. This will
+calculate the checksums of the classpath elements. `ContextDefinition.toJson()`
+can be used to serialize the `ContextDefinition` to a `String` to store in a
+file.
Alternatively, if this library's jar is built and placed onto Accumulo's
`CLASSPATH`, then one can run `bin/accumulo create-context-definition` to
@@ -136,8 +145,9 @@ create the ContextDefinition json file using the
command-line. The resulting
json is printed to stdout and can be redirected to a file. The command takes
two arguments:
-1. the monitor interval, in seconds (e.g. `-i 300`), and
-2. a list of file URLs (e.g. `hdfs://host:port/path/to/one.jar
file://host/path/to/two.jar`)
+1. the monitor interval, in seconds (e.g. `-i 300`),
+2. an optional checksum algorithm to use (e.g. `-a 'SHA3-512'`), and
+3. a list of file URLs (e.g. `hdfs://host:port/path/to/one.jar
file://host/path/to/two.jar`)
## Updating a ContextDefinition file
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
index 13d6a38..dd232c1 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
@@ -52,7 +52,6 @@ import
org.apache.accumulo.classloader.lcc.jmx.ContextClassLoadersMXBean;
import org.apache.accumulo.classloader.lcc.util.DeduplicationCache;
import org.apache.accumulo.classloader.lcc.util.LccUtils;
import org.apache.accumulo.classloader.lcc.util.LocalStore;
-import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.spi.common.ContextClassLoaderEnvironment;
import org.apache.accumulo.core.spi.common.ContextClassLoaderFactory;
import org.slf4j.Logger;
@@ -68,8 +67,8 @@ import com.google.common.base.Stopwatch;
* {@link ContextDefinition} file. The file contains an interval at which this
class should monitor
* the file for changes and a list of {@link Resource} objects. If the
monitoring fails for a period
* configurable with the {@link #UPDATE_FAILURE_GRACE_PERIOD_MINS} property,
then monitoring will
- * discontinue until the next use of that context. Each resource is defined by
a URL to the file and
- * an expected SHA-256 checksum.
+ * discontinue until the next use of that context. Each resource is defined by
a URL to the file, a
+ * checksum algorithm, and a checksum.
* <p>
* The URLs supplied for the context definition file and for the resources may
use any URL type with
* a registered provider in your application, such as: file, http, https, or
hdfs.
@@ -90,11 +89,10 @@ import com.google.common.base.Stopwatch;
*/
public class LocalCachingContextClassLoaderFactory implements
ContextClassLoaderFactory {
- public static final String CACHE_DIR_PROPERTY =
- Property.GENERAL_ARBITRARY_PROP_PREFIX.getKey() +
"classloader.lcc.cache.dir";
+ public static final String CACHE_DIR_PROPERTY =
"general.custom.classloader.lcc.cache.dir";
public static final String UPDATE_FAILURE_GRACE_PERIOD_MINS =
- Property.GENERAL_ARBITRARY_PROP_PREFIX.getKey() +
"classloader.lcc.update.grace.minutes";
+ "general.custom.classloader.lcc.update.grace.minutes";
private static final Logger LOG =
LoggerFactory.getLogger(LocalCachingContextClassLoaderFactory.class);
@@ -215,8 +213,8 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
} else {
computedDefinition = previousDefinition;
}
- final URLClassLoader classloader = classloaders.computeIfAbsent(
- newCacheKey(contextLocation, computedDefinition.getChecksum()),
(Supplier<URL[]>) () -> {
+ final URLClassLoader classloader = classloaders
+ .computeIfAbsent(newCacheKey(contextLocation, computedDefinition),
(Supplier<URL[]>) () -> {
try {
return localStore.get().storeContextResources(computedDefinition);
} catch (IOException e) {
@@ -233,16 +231,16 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
return ContextDefinition.fromRemoteURL(url);
}
- private static String newCacheKey(String contextLocation, String
contextChecksum) {
- // the checksum can't contain '-', so everything before the last one is
the location
- return contextLocation + "-" + contextChecksum;
+ private static String newCacheKey(String contextLocation, ContextDefinition
contextDefinition) {
+ // the location is between the first left parenthesis and the last right
parenthesis
+ return contextDefinition.getChecksumAlgorithm() + " (" + contextLocation +
") = "
+ + contextDefinition.getChecksum();
}
private static boolean cacheKeyMatchesContextLocation(String cacheKey,
String contextLocation) {
- // the checksum can't contain '-', so everything before the last one is
the location
- // we can't just use startsWith(contextLocation) because there may be
other contextLocations
- // that contain this contextLocation as a prefix, so we do an exact match
on the location part
- return cacheKey.substring(0,
cacheKey.lastIndexOf('-')).equals(contextLocation);
+ // extract the location from the parentheses in the cacheKey
+ return cacheKey.substring(cacheKey.indexOf('(') + 1,
cacheKey.lastIndexOf(')'))
+ .equals(contextLocation);
}
private void checkMonitoredLocation(String contextLocation, long interval) {
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/ContextDefinition.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/ContextDefinition.java
index 4278e25..2e42cec 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/ContextDefinition.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/ContextDefinition.java
@@ -21,8 +21,9 @@ package org.apache.accumulo.classloader.lcc.definition;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.hash;
import static java.util.Objects.requireNonNull;
-import static org.apache.accumulo.classloader.lcc.util.LccUtils.DIGESTER;
+import static org.apache.accumulo.classloader.lcc.util.LccUtils.getDigester;
+import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -34,12 +35,14 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.function.Supplier;
-import org.apache.accumulo.core.cli.Help;
import org.apache.accumulo.start.spi.KeywordExecutable;
+import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
+import com.beust.jcommander.ParameterException;
import com.google.auto.service.AutoService;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
@@ -51,14 +54,55 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@AutoService(KeywordExecutable.class)
public class ContextDefinition implements KeywordExecutable {
- static class Opts extends Help {
+ static class Opts {
@Parameter(names = {"-i", "--interval"}, required = true,
description = "monitor interval (in seconds)", arity = 1, order = 1)
int monitorInterval;
+ @Parameter(names = {"-a", "--algorithm"}, required = false,
+ description = "checksum algorithm to use (default: " + SHA_512 + ")",
arity = 1, order = 2)
+ String algorithm = SHA_512;
+
@Parameter(required = true, description = "classpath element URL (<url>[
<url>...])",
- arity = -1, order = 2)
+ arity = -1, order = 3)
public List<String> files = new ArrayList<>();
+
+ @Parameter(names = {"-h", "-?", "--help", "-help"}, help = true)
+ public boolean help = false;
+
+ void parseArgs(Consumer<JCommander> jcConsumer, String programName,
String[] args,
+ Object... others) {
+ JCommander commander = new JCommander();
+ jcConsumer.accept(commander);
+ commander.addObject(this);
+ for (Object other : others) {
+ commander.addObject(other);
+ }
+ commander.setProgramName(programName);
+ try {
+ commander.parse(args);
+ } catch (ParameterException ex) {
+ commander.usage();
+ exitWithError(ex.getMessage(), 1);
+ }
+ if (help) {
+ commander.usage();
+ exit(0);
+ }
+ }
+
+ void parseArgs(String programName, String[] args, Object... others) {
+ parseArgs(jCommander -> {}, programName, args, others);
+ }
+
+ void exit(int status) {
+ System.exit(status);
+ }
+
+ void exitWithError(String message, int status) {
+ System.err.println(message);
+ exit(status);
+ }
}
// pretty-print uses Unix newline
@@ -67,13 +111,13 @@ public class ContextDefinition implements
KeywordExecutable {
@SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD",
justification = "user-supplied URL is the intended functionality")
- public static ContextDefinition create(int monitorIntervalSecs, URL...
sources)
+ public static ContextDefinition create(int monitorIntervalSecs, String
algorithm, URL... sources)
throws IOException {
LinkedHashSet<Resource> resources = new LinkedHashSet<>();
for (URL u : sources) {
- try (InputStream is = u.openStream()) {
- String checksum = DIGESTER.digestAsHex(is);
- resources.add(new Resource(u, checksum));
+ try (InputStream is = new BufferedInputStream(u.openStream())) {
+ String checksum = getDigester(algorithm).digestAsHex(is);
+ resources.add(new Resource(u, algorithm, checksum));
}
}
return new ContextDefinition(monitorIntervalSecs, resources);
@@ -91,9 +135,11 @@ public class ContextDefinition implements KeywordExecutable
{
}
}
+ private static final String SHA_512 = "SHA-512";
+
// transient fields that don't go in the json
private final transient Supplier<String> checksum =
- Suppliers.memoize(() -> DIGESTER.digestAsHex(toJson()));
+ Suppliers.memoize(() ->
getDigester(getChecksumAlgorithm()).digestAsHex(toJson()));
// serialized fields for json
// use a LinkedHashSet to preserve the order specified in the context file
@@ -138,6 +184,10 @@ public class ContextDefinition implements
KeywordExecutable {
&& Objects.equals(resources, other.resources);
}
+ public String getChecksumAlgorithm() {
+ return SHA_512;
+ }
+
public String getChecksum() {
return checksum.get();
}
@@ -168,7 +218,7 @@ public class ContextDefinition implements KeywordExecutable
{
for (String f : opts.files) {
urls[count++] = new URL(f);
}
- ContextDefinition def = create(opts.monitorInterval, urls);
+ ContextDefinition def = create(opts.monitorInterval, opts.algorithm, urls);
System.out.print(def.toJson());
}
}
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/Resource.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/Resource.java
index 70afdde..9aef499 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/Resource.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/definition/Resource.java
@@ -20,24 +20,48 @@ package org.apache.accumulo.classloader.lcc.definition;
import java.net.URL;
import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.Objects;
public class Resource {
private URL location;
+ private String algorithm;
private String checksum;
public Resource() {}
- public Resource(URL location, String checksum) {
+ public Resource(URL location, String algorithm, String checksum) {
this.location = location;
+ this.algorithm = normalizeAlgorithm(algorithm);
this.checksum = checksum;
}
+ protected static String normalizeAlgorithm(String algorithm) {
+ try {
+ // try to normalize the algorithm name by finding the provider, then
getting the MessageDigest
+ // service for that algorithm, and asking that service for the canonical
algorithm name
+ return MessageDigest.getInstance(algorithm).getProvider()
+ .getService("MessageDigest", algorithm).getAlgorithm();
+ } catch (NoSuchAlgorithmException e) {
+ // just keep the provided name if we can't find a provider for that
algorithm
+ return algorithm;
+ }
+ }
+
public URL getLocation() {
return location;
}
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ public String getChecksum() {
+ return checksum;
+ }
+
public String getFileName() {
var nameAsPath = Path.of(location.getPath()).getFileName();
if (nameAsPath == null) {
@@ -50,10 +74,6 @@ public class Resource {
return name;
}
- public String getChecksum() {
- return checksum;
- }
-
@Override
public int hashCode() {
return Objects.hash(location, checksum);
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LccUtils.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LccUtils.java
index 22a8f1d..a971e81 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LccUtils.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LccUtils.java
@@ -20,6 +20,7 @@ package org.apache.accumulo.classloader.lcc.util;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.concurrent.ConcurrentHashMap;
import
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory;
import org.apache.commons.codec.digest.DigestUtils;
@@ -31,7 +32,12 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
public class LccUtils {
private static final Logger LOG = LoggerFactory.getLogger(LccUtils.class);
- public static final DigestUtils DIGESTER = new
DigestUtils(DigestUtils.getSha256Digest());
+ private static final ConcurrentHashMap<String,DigestUtils> DIGESTERS = new
ConcurrentHashMap<>();
+
+ // keep at most one DigestUtils instance for each algorithm
+ public static DigestUtils getDigester(String algorithm) {
+ return DIGESTERS.computeIfAbsent(algorithm, DigestUtils::new);
+ }
@SuppressFBWarnings(value = "DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED",
justification = "doPrivileged is deprecated without replacement and
removed in newer Java")
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
index 9d533bb..81cedad 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
@@ -25,7 +25,7 @@ import static java.nio.file.StandardOpenOption.SYNC;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
import static java.nio.file.StandardOpenOption.WRITE;
import static java.util.Objects.requireNonNull;
-import static org.apache.accumulo.classloader.lcc.util.LccUtils.DIGESTER;
+import static org.apache.accumulo.classloader.lcc.util.LccUtils.getDigester;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -116,7 +116,7 @@ public final class LocalStore {
public static String localResourceName(Resource r) {
requireNonNull(r);
String remoteFileName = r.getFileName();
- String checksum = r.getChecksum();
+ String checksum = checksumForFileName(r.getAlgorithm(), r.getChecksum());
var matcher = fileNamesWithExtensionPattern.matcher(remoteFileName);
if (matcher.matches()) {
return String.format("%s-%s.%s", matcher.group(1), checksum,
matcher.group(2));
@@ -128,6 +128,10 @@ public final class LocalStore {
return "." + requireNonNull(baseName) + "_PID" + PID + "_" +
UUID.randomUUID() + ".tmp";
}
+ static String checksumForFileName(String algorithm, String checksum) {
+ return algorithm.replace('/', '_') + "-" + checksum;
+ }
+
/**
* Save the {@link ContextDefinition} to the contexts directory, and all of
its resources to the
* resources directory.
@@ -136,7 +140,8 @@ public final class LocalStore {
requireNonNull(contextDefinition, "definition must be supplied");
// use a LinkedHashSet to preserve the order of the context resources
final Set<Path> localFiles = new LinkedHashSet<>();
- final String destinationName = contextDefinition.getChecksum() + ".json";
+ final String destinationName =
checksumForFileName(contextDefinition.getChecksumAlgorithm(),
+ contextDefinition.getChecksum()) + ".json";
try {
storeContextDefinition(contextDefinition, destinationName);
boolean successful = false;
@@ -310,9 +315,10 @@ public final class LocalStore {
}
private void verifyDownload(Resource resource, Path downloadPath, Closeable
cleanUpAction) {
+ final String algorithm = resource.getAlgorithm();
final String checksum;
try {
- checksum = DIGESTER.digestAsHex(downloadPath);
+ checksum = getDigester(algorithm).digestAsHex(downloadPath);
} catch (IOException e) {
throw new UncheckedIOException("Unable to perform checksum verification
on " + downloadPath
+ " for resource " + resource.getLocation(), e);
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
index 8a0cb31..72d8824 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
@@ -70,6 +70,8 @@ import com.google.gson.JsonSyntaxException;
public class LocalCachingContextClassLoaderFactoryTest {
protected static final int MONITOR_INTERVAL_SECS = 5;
+ // MD5 sum for "bad"
+ private static final String BAD_MD5 = "bae60998ffe4923b131e3d6e4c19993e";
private static MiniDFSCluster hdfs;
private static FileSystem fs;
private static Server jetty;
@@ -128,7 +130,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
final URL jarCJettyLocation = jetty.getURI().resolve("TestC.jar").toURL();
// ContextDefinition with all jars
- var allJarsDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation,
+ var allJarsDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
"SHA-512", jarAOrigLocation,
jarBHdfsLocation, jarCJettyLocation, jarDOrigLocation);
String allJarsDefJson = allJarsDef.toJson();
@@ -225,7 +227,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testInitialInvalidJson() throws Exception {
// Create a new context definition file in HDFS, but with invalid content
- var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
// write out invalid json
final var invalid = createContextDefinitionFile(fs,
"InvalidContextDefinitionFile.json",
def.toJson().substring(0, 4));
@@ -239,7 +241,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testInitial() throws Exception {
- var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var initial =
createContextDefinitionFile(fs, "InitialContextDefinitionFile.json",
def.toJson());
final URL initialDefUrl = new URL(fs.getUri().toString() +
initial.toUri().toString());
@@ -263,7 +265,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
Files.copy(jarAPath, jarACopy, StandardCopyOption.REPLACE_EXISTING);
assertTrue(Files.exists(jarACopy));
- var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarACopy.toUri().toURL());
+ var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarACopy.toUri().toURL());
Files.delete(jarACopy);
assertTrue(!Files.exists(jarACopy));
@@ -289,7 +291,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testInitialBadResourceURL() throws Exception {
LinkedHashSet<Resource> resources = new LinkedHashSet<>();
- resources.add(new Resource(jarAOrigLocation, "1234"));
+ resources.add(new Resource(jarAOrigLocation, "MD5", BAD_MD5));
// remove the file:// prefix from the URL
String goodJson = new ContextDefinition(MONITOR_INTERVAL_SECS,
resources).toJson();
@@ -313,7 +315,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testInitialBadResourceChecksum() throws Exception {
- Resource r = new Resource(jarAOrigLocation, "1234");
+ Resource r = new Resource(jarAOrigLocation, "MD5", BAD_MD5);
LinkedHashSet<Resource> resources = new LinkedHashSet<>();
resources.add(r);
@@ -340,7 +342,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdate() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateContextDefinitionFile.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -353,7 +355,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
testClassFailsToLoad(cl, classD);
// Update the contents of the context definition json file
- var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarDOrigLocation);
+ var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarDOrigLocation);
updateContextDefinitionFile(fs, defFilePath, updateDef.toJson());
// wait 2x the monitor interval
@@ -371,7 +373,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateSameClassNameDifferentContent() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateContextDefinitionFile.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -384,7 +386,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
testClassFailsToLoad(cl, classD);
// Update the contents of the context definition json file
- var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarEOrigLocation);
+ var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarEOrigLocation);
updateContextDefinitionFile(fs, defFilePath, updateDef.toJson());
// wait 2x the monitor interval
@@ -404,7 +406,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateContextDefinitionEmpty() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs,
"UpdateEmptyContextDefinitionFile.json", def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -435,7 +437,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateNonExistentResource() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateNonExistentResource.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -457,7 +459,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
assertTrue(!Files.exists(jarACopy));
Files.copy(jarAPath, jarACopy, StandardCopyOption.REPLACE_EXISTING);
assertTrue(Files.exists(jarACopy));
- var def2 = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarACopy.toUri().toURL());
+ var def2 = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarACopy.toUri().toURL());
Files.delete(jarACopy);
assertTrue(!Files.exists(jarACopy));
@@ -478,7 +480,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateBadResourceChecksum() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateBadResourceChecksum.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -490,7 +492,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
testClassFailsToLoad(cl, classC);
testClassFailsToLoad(cl, classD);
- Resource r = new Resource(jarAOrigLocation, "1234");
+ Resource r = new Resource(jarAOrigLocation, "MD5", BAD_MD5);
LinkedHashSet<Resource> resources = new LinkedHashSet<>();
resources.add(r);
@@ -513,7 +515,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateBadResourceURL() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateBadResourceChecksum.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -527,7 +529,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
// remove the file:// prefix from the URL
LinkedHashSet<Resource> resources = new LinkedHashSet<>();
- resources.add(new Resource(jarAOrigLocation, "1234"));
+ resources.add(new Resource(jarAOrigLocation, "MD5", BAD_MD5));
String goodJson = new ContextDefinition(MONITOR_INTERVAL_SECS,
resources).toJson();
String badJson =
goodJson.replace(jarAOrigLocation.toString(),
jarAOrigLocation.toString().substring(6));
@@ -550,7 +552,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testUpdateInvalidJson() throws Exception {
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs,
"UpdateInvalidContextDefinitionFile.json", def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -562,7 +564,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
testClassFailsToLoad(cl, classC);
testClassFailsToLoad(cl, classD);
- var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarDOrigLocation);
+ var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarDOrigLocation);
updateContextDefinitionFile(fs, defFilePath,
updateDef.toJson().substring(0, 4));
// wait 2x the monitor interval
@@ -595,8 +597,8 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testChangingContext() throws Exception {
- var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation, jarBOrigLocation,
- jarCOrigLocation, jarDOrigLocation);
+ var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation,
+ jarBOrigLocation, jarCOrigLocation, jarDOrigLocation);
final var update =
createContextDefinitionFile(fs,
"UpdateChangingContextDefinition.json", def.toJson());
final URL updatedDefUrl = new URL(fs.getUri().toString() +
update.toUri().toString());
@@ -622,8 +624,8 @@ public class LocalCachingContextClassLoaderFactoryTest {
final URL removed = updatedList.remove(0);
// Update the contents of the context definition json file
- var updateDef =
- ContextDefinition.create(MONITOR_INTERVAL_SECS,
updatedList.toArray(new URL[0]));
+ var updateDef = ContextDefinition.create(MONITOR_INTERVAL_SECS,
"SHA-512",
+ updatedList.toArray(new URL[0]));
updateContextDefinitionFile(fs, update, updateDef.toJson());
// wait 2x the monitor interval
@@ -675,7 +677,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
Map.of(CACHE_DIR_PROPERTY, baseCacheDir,
UPDATE_FAILURE_GRACE_PERIOD_MINS, "1"));
localFactory.init(() -> new ConfigurationImpl(acuConf));
- final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation);
+ final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateNonExistentResource.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
@@ -697,7 +699,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
assertTrue(!Files.exists(jarACopy));
Files.copy(jarAPath, jarACopy, StandardCopyOption.REPLACE_EXISTING);
assertTrue(Files.exists(jarACopy));
- var def2 = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarACopy.toUri().toURL());
+ var def2 = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarACopy.toUri().toURL());
Files.delete(jarACopy);
assertTrue(!Files.exists(jarACopy));
@@ -734,8 +736,8 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testExternalFileModification() throws Exception {
- var def = ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarAOrigLocation, jarBOrigLocation,
- jarCOrigLocation, jarDOrigLocation);
+ var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation,
+ jarBOrigLocation, jarCOrigLocation, jarDOrigLocation);
final var update =
createContextDefinitionFile(fs,
"UpdateChangingContextDefinition.json", def.toJson());
final URL updatedDefUrl = new URL(fs.getUri().toString() +
update.toUri().toString());
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
index b364354..8ebad35 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
@@ -158,8 +158,8 @@ public class MiniAccumuloClusterClassLoaderFactoryTest
extends SharedMiniCluster
Files.createDirectory(jsonDirPath, PERMISSIONS);
// Create a context definition that only references jar A
- final ContextDefinition testContextDef =
- ContextDefinition.create(MONITOR_INTERVAL_SECS, jarAOrigLocation);
+ final var testContextDef =
+ ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-256",
jarAOrigLocation);
final String testContextDefJson = testContextDef.toJson();
final File testContextDefFile =
jsonDirPath.resolve("testContextDefinition.json").toFile();
Files.writeString(testContextDefFile.toPath(), testContextDefJson,
StandardOpenOption.CREATE);
@@ -245,7 +245,7 @@ public class MiniAccumuloClusterClassLoaderFactoryTest
extends SharedMiniCluster
// Update the context definition to point to jar B
final ContextDefinition testContextDefUpdate =
- ContextDefinition.create(MONITOR_INTERVAL_SECS, jarBOrigLocation);
+ ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarBOrigLocation);
final String testContextDefUpdateJson = testContextDefUpdate.toJson();
Files.writeString(testContextDefFile.toPath(), testContextDefUpdateJson,
StandardOpenOption.TRUNCATE_EXISTING);
@@ -281,7 +281,7 @@ public class MiniAccumuloClusterClassLoaderFactoryTest
extends SharedMiniCluster
assertTrue(Files.exists(jarACopy));
final ContextDefinition testContextDefUpdate2 =
- ContextDefinition.create(MONITOR_INTERVAL_SECS,
jarACopy.toUri().toURL());
+ ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarACopy.toUri().toURL());
Files.delete(jarACopy);
assertTrue(!Files.exists(jarACopy));
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/TestUtils.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/TestUtils.java
index d625a68..9811f4e 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/TestUtils.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/TestUtils.java
@@ -19,7 +19,7 @@
package org.apache.accumulo.classloader.lcc;
import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.accumulo.classloader.lcc.util.LccUtils.DIGESTER;
+import static org.apache.accumulo.classloader.lcc.util.LccUtils.getDigester;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -170,9 +170,10 @@ public class TestUtils {
@SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD",
justification = "user-supplied URL is the intended functionality")
- public static String computeResourceChecksum(URL resourceLocation) throws
IOException {
+ public static String computeResourceChecksum(String algorithm, URL
resourceLocation)
+ throws IOException {
try (InputStream is = resourceLocation.openStream()) {
- return DIGESTER.digestAsHex(is);
+ return getDigester(algorithm).digestAsHex(is);
}
}
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
index 86e6d94..3d637ab 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
@@ -20,6 +20,7 @@ package org.apache.accumulo.classloader.lcc.util;
import static
org.apache.accumulo.classloader.lcc.TestUtils.testClassFailsToLoad;
import static org.apache.accumulo.classloader.lcc.TestUtils.testClassLoads;
+import static
org.apache.accumulo.classloader.lcc.util.LocalStore.localResourceName;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
@@ -91,12 +92,12 @@ public class LocalStoreTest {
// Create ContextDefinition with all three resources
final LinkedHashSet<Resource> resources = new LinkedHashSet<>();
- resources
- .add(new Resource(jarAOrigLocation,
TestUtils.computeResourceChecksum(jarAOrigLocation)));
- resources
- .add(new Resource(jarBNewLocation,
TestUtils.computeResourceChecksum(jarBOrigLocation)));
- resources
- .add(new Resource(jarCNewLocation,
TestUtils.computeResourceChecksum(jarCOrigLocation)));
+ resources.add(new Resource(jarAOrigLocation, "SHA-256",
+ TestUtils.computeResourceChecksum("SHA-256", jarAOrigLocation)));
+ resources.add(new Resource(jarBNewLocation, "SHA-512",
+ TestUtils.computeResourceChecksum("SHA-512", jarBOrigLocation)));
+ resources.add(new Resource(jarCNewLocation, "SHA-1",
+ TestUtils.computeResourceChecksum("SHA-1", jarCOrigLocation)));
def = new ContextDefinition(MONITOR_INTERVAL_SECS, resources);
classA = new TestClassInfo("test.TestObjectA", "Hello from A");
@@ -151,13 +152,18 @@ public class LocalStoreTest {
assertTrue(Files.exists(baseCacheDir));
}
- private static Resource rsrc(String filename, String checksum) {
+ private static Resource rsrc(String filename, String algorithm, String
checksum) {
return new Resource() {
@Override
public String getFileName() {
return filename;
}
+ @Override
+ public String getAlgorithm() {
+ return normalizeAlgorithm(algorithm);
+ }
+
@Override
public String getChecksum() {
return checksum;
@@ -167,31 +173,42 @@ public class LocalStoreTest {
@Test
public void testLocalFileName() {
+ // regular jar, test various algorithm name normalizations
+ assertEquals("f0-MD5-chk0.jar", localResourceName(rsrc("f0.jar", "md5",
"chk0")));
+ assertEquals("f0-MD5-chk0.jar", localResourceName(rsrc("f0.jar", "MD5",
"chk0")));
+ assertEquals("f0-SHA-1-chk0.jar", localResourceName(rsrc("f0.jar", "sha1",
"chk0")));
+ assertEquals("f0-SHA-1-chk0.jar", localResourceName(rsrc("f0.jar",
"Sha-1", "chk0")));
+ assertEquals("f0-SHA-1-chk0.jar", localResourceName(rsrc("f0.jar",
"SHA-1", "chk0")));
+ assertEquals("f0-SHA-512-chk0.jar", localResourceName(rsrc("f0.jar",
"sha512", "chk0")));
+ assertEquals("f0-SHA-512_224-chk0.jar",
+ localResourceName(rsrc("f0.jar", "sha512/224", "chk0")));
+ assertEquals("f0-SHA3-224-chk0.jar", localResourceName(rsrc("f0.jar",
"sha3-224", "chk0")));
+
// regular war
- assertEquals("f1-chk1.war", LocalStore.localResourceName(rsrc("f1.war",
"chk1")));
+ assertEquals("f1-mock-chk1.war", localResourceName(rsrc("f1.war", "mock",
"chk1")));
// dotfile war
- assertEquals(".f1-chk1.war", LocalStore.localResourceName(rsrc(".f1.war",
"chk1")));
+ assertEquals(".f1-mock-chk1.war", localResourceName(rsrc(".f1.war",
"mock", "chk1")));
// regular jar (has multiple dots)
- assertEquals("f2-1.0-chk2.jar",
LocalStore.localResourceName(rsrc("f2-1.0.jar", "chk2")));
+ assertEquals("f2-1.0-mock-chk2.jar", localResourceName(rsrc("f2-1.0.jar",
"mock", "chk2")));
// dotfile jar (has multiple dots)
- assertEquals(".f2-1.0-chk2.jar",
LocalStore.localResourceName(rsrc(".f2-1.0.jar", "chk2")));
+ assertEquals(".f2-1.0-mock-chk2.jar",
localResourceName(rsrc(".f2-1.0.jar", "mock", "chk2")));
// regular file with no suffix
- assertEquals("f3-chk3", LocalStore.localResourceName(rsrc("f3", "chk3")));
+ assertEquals("f3-mock-chk3", localResourceName(rsrc("f3", "mock",
"chk3")));
// weird files with trailing dots and no file suffix
- assertEquals("f4.-chk4", LocalStore.localResourceName(rsrc("f4.",
"chk4")));
- assertEquals("f4..-chk4", LocalStore.localResourceName(rsrc("f4..",
"chk4")));
- assertEquals("f4...-chk4", LocalStore.localResourceName(rsrc("f4...",
"chk4")));
+ assertEquals("f4.-mock-chk4", localResourceName(rsrc("f4.", "mock",
"chk4")));
+ assertEquals("f4..-mock-chk4", localResourceName(rsrc("f4..", "mock",
"chk4")));
+ assertEquals("f4...-mock-chk4", localResourceName(rsrc("f4...", "mock",
"chk4")));
// weird dotfiles that don't really have a suffix
- assertEquals(".f5-chk5", LocalStore.localResourceName(rsrc(".f5",
"chk5")));
- assertEquals("..f5-chk5", LocalStore.localResourceName(rsrc("..f5",
"chk5")));
+ assertEquals(".f5-mock-chk5", localResourceName(rsrc(".f5", "mock",
"chk5")));
+ assertEquals("..f5-mock-chk5", localResourceName(rsrc("..f5", "mock",
"chk5")));
// weird files with weird dots, but do have a valid suffix
- assertEquals("f6.-chk6.jar", LocalStore.localResourceName(rsrc("f6..jar",
"chk6")));
- assertEquals("f6..-chk6.jar",
LocalStore.localResourceName(rsrc("f6...jar", "chk6")));
- assertEquals(".f6-chk6.jar", LocalStore.localResourceName(rsrc(".f6.jar",
"chk6")));
- assertEquals("..f6-chk6.jar",
LocalStore.localResourceName(rsrc("..f6.jar", "chk6")));
- assertEquals(".f6.-chk6.jar",
LocalStore.localResourceName(rsrc(".f6..jar", "chk6")));
- assertEquals("..f6.-chk6.jar",
LocalStore.localResourceName(rsrc("..f6..jar", "chk6")));
+ assertEquals("f6.-mock-chk6.jar", localResourceName(rsrc("f6..jar",
"mock", "chk6")));
+ assertEquals("f6..-mock-chk6.jar", localResourceName(rsrc("f6...jar",
"mock", "chk6")));
+ assertEquals(".f6-mock-chk6.jar", localResourceName(rsrc(".f6.jar",
"mock", "chk6")));
+ assertEquals("..f6-mock-chk6.jar", localResourceName(rsrc("..f6.jar",
"mock", "chk6")));
+ assertEquals(".f6.-mock-chk6.jar", localResourceName(rsrc(".f6..jar",
"mock", "chk6")));
+ assertEquals("..f6.-mock-chk6.jar", localResourceName(rsrc("..f6..jar",
"mock", "chk6")));
}
@Test
@@ -201,10 +218,10 @@ public class LocalStoreTest {
// Confirm the 3 jars are cached locally
assertTrue(Files.exists(baseCacheDir));
-
assertTrue(Files.exists(baseCacheDir.resolve("contexts").resolve(def.getChecksum()
+ ".json")));
+ assertTrue(Files.exists(baseCacheDir.resolve("contexts").resolve(
+ LocalStore.checksumForFileName(def.getChecksumAlgorithm(),
def.getChecksum()) + ".json")));
for (Resource r : def.getResources()) {
- assertTrue(
-
Files.exists(baseCacheDir.resolve("resources").resolve(LocalStore.localResourceName(r))));
+
assertTrue(Files.exists(baseCacheDir.resolve("resources").resolve(localResourceName(r))));
}
}
@@ -237,25 +254,25 @@ public class LocalStoreTest {
// Add D
final URL jarDOrigLocation =
LocalStoreTest.class.getResource("/ClassLoaderTestD/TestD.jar");
assertNotNull(jarDOrigLocation);
- updatedResources
- .add(new Resource(jarDOrigLocation,
TestUtils.computeResourceChecksum(jarDOrigLocation)));
+ updatedResources.add(new Resource(jarDOrigLocation, "SHA-512",
+ TestUtils.computeResourceChecksum("SHA-512", jarDOrigLocation)));
var updatedDef = new ContextDefinition(MONITOR_INTERVAL_SECS,
updatedResources);
urls = localStore.storeContextResources(updatedDef);
// Confirm the 3 jars are cached locally
- assertTrue(
-
Files.exists(baseCacheDir.resolve("contexts").resolve(updatedDef.getChecksum()
+ ".json")));
+ assertTrue(Files.exists(baseCacheDir.resolve("contexts").resolve(
+ LocalStore.checksumForFileName(updatedDef.getChecksumAlgorithm(),
updatedDef.getChecksum())
+ + ".json")));
for (Resource r : updatedDef.getResources()) {
assertFalse(r.getFileName().contains("C"));
- assertTrue(
-
Files.exists(baseCacheDir.resolve("resources").resolve(LocalStore.localResourceName(r))));
+
assertTrue(Files.exists(baseCacheDir.resolve("resources").resolve(localResourceName(r))));
}
assertTrue(removedResource.getFileName().contains("C"),
"cache location should still contain 'C'");
- assertTrue(Files.exists(
-
baseCacheDir.resolve("resources").resolve(LocalStore.localResourceName(removedResource))));
+ assertTrue(Files
+
.exists(baseCacheDir.resolve("resources").resolve(localResourceName(removedResource))));
final var updatedContextClassLoader = LccUtils.createClassLoader("url",
urls);
diff --git a/pom.xml b/pom.xml
index 16766a5..934a65c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -472,93 +472,6 @@ under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
- <configuration>
- <checkstyleRules>
- <module name="Checker">
- <property name="charset" value="UTF-8" />
- <property name="severity" value="warning" />
- <!-- Checks for whitespace -->
- <!-- See
https://checkstyle.sourceforge.io/config_whitespace.html -->
- <module name="FileTabCharacter" />
- <module name="TreeWalker">
- <module name="OneTopLevelClass" />
- <module name="RegexpSinglelineJava">
- <property name="format" value="\s+$" />
- <property name="message" value="Line has trailing
whitespace." />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="[@]Deprecated([^)]*forRemoval[^)]*)" />
- <property name="message" value="forRemoval should not be
used." />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="[@]see\s+[{][@]link" />
- <property name="message" value="Javadoc @see does not need
@link: pick one or the other." />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="jline[.]internal[.]Preconditions" />
- <property name="message" value="Please use Guava
Preconditions not JLine" />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="org[.]apache[.]commons[.]math[.]" />
- <property name="message" value="Use commons-math3
(org.apache.commons.math3.*)" />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="org[.]junit[.]jupiter[.]api[.]Assertions;" />
- <property name="message" value="Use static imports for
Assertions.* methods for consistency" />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="org[.]junit[.]jupiter[.]api[.]Assumptions;" />
- <property name="message" value="Use static imports for
Assumptions.* methods for consistency" />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format" value="import
java[.]nio[.]charset[.]StandardCharsets;" />
- <property name="message" value="Use static imports for
StandardCharsets.* constants for consistency" />
- </module>
- <module name="RegexpSinglelineJava">
- <!-- double escape quotes because checkstyle passes these
through another xml parser -->
- <property name="format" value="&quot; [+] &quot;" />
- <property name="message" value="Unnecessary concatenation of
string literals" />
- </module>
- <module name="RegexpSinglelineJava">
- <property name="format"
value="com[.]google[.]common[.]cache[.]" />
- <property name="message" value="Please use Caffeine Cache,
not Guava" />
- </module>
- <module name="OuterTypeFilename" />
- <module name="AvoidStarImport" />
- <module name="NoLineWrap" />
- <module name="LeftCurly" />
- <module name="RightCurly">
- <property name="tokens" value="LITERAL_TRY, LITERAL_CATCH,
LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, CLASS_DEF, METHOD_DEF, CTOR_DEF,
LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT" />
- </module>
- <module name="SeparatorWrap">
- <property name="tokens" value="DOT" />
- <property name="option" value="nl" />
- </module>
- <module name="SeparatorWrap">
- <property name="tokens" value="COMMA" />
- <property name="option" value="EOL" />
- </module>
- <module name="PackageName">
- <property name="format"
value="^[a-z]+(\.[a-z][a-zA-Z0-9]*)*$" />
- </module>
- <module name="MethodTypeParameterName">
- <property name="format"
value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
- </module>
- <module name="NonEmptyAtclauseDescription" />
- <module name="JavadocMethod">
- <property name="allowMissingParamTags" value="true" />
- <property name="allowMissingReturnTag" value="true" />
- <property name="allowedAnnotations"
value="Override,Test,BeforeClass,AfterClass,Before,After,BeforeAll,AfterAll,BeforeEach,AfterEach"
/>
- </module>
- <module name="MissingOverrideCheck" />
- <!--Require braces for all control statements -->
- <module name="NeedBraces" />
- </module>
- </module>
- </checkstyleRules>
- <violationSeverity>warning</violationSeverity>
- <includeTestSourceDirectory>true</includeTestSourceDirectory>
- </configuration>
<dependencies>
<dependency>
<groupId>com.puppycrawl.tools</groupId>
@@ -572,6 +485,115 @@ under the License.
<goals>
<goal>check</goal>
</goals>
+ <configuration>
+ <checkstyleRules>
+ <module name="Checker">
+ <property name="charset" value="UTF-8" />
+ <property name="severity" value="warning" />
+ <!-- Checks for whitespace -->
+ <!-- See
https://checkstyle.sourceforge.io/config_whitespace.html -->
+ <module name="FileTabCharacter" />
+ <module name="TreeWalker">
+ <module name="OneTopLevelClass" />
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="\s+$" />
+ <property name="message" value="Line has trailing
whitespace." />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="[@]Deprecated([^)]*forRemoval[^)]*)" />
+ <property name="message" value="forRemoval should not be
used." />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="[@]see\s+[{][@]link" />
+ <property name="message" value="Javadoc @see does not
need @link: pick one or the other." />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="jline[.]internal[.]Preconditions" />
+ <property name="message" value="Please use Guava
Preconditions not JLine" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="org[.]apache[.]commons[.]math[.]" />
+ <property name="message" value="Use commons-math3
(org.apache.commons.math3.*)" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="org[.]junit[.]jupiter[.]api[.]Assertions;" />
+ <property name="message" value="Use static imports for
Assertions.* methods for consistency" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="org[.]junit[.]jupiter[.]api[.]Assumptions;" />
+ <property name="message" value="Use static imports for
Assumptions.* methods for consistency" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format" value="import
java[.]nio[.]charset[.]StandardCharsets;" />
+ <property name="message" value="Use static imports for
StandardCharsets.* constants for consistency" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <!-- double escape quotes because checkstyle passes
these through another xml parser -->
+ <property name="format" value="&quot; [+]
&quot;" />
+ <property name="message" value="Unnecessary
concatenation of string literals" />
+ </module>
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="com[.]google[.]common[.]cache[.]" />
+ <property name="message" value="Please use Caffeine
Cache, not Guava" />
+ </module>
+ <module name="OuterTypeFilename" />
+ <module name="AvoidStarImport" />
+ <module name="NoLineWrap" />
+ <module name="LeftCurly" />
+ <module name="RightCurly">
+ <property name="tokens" value="LITERAL_TRY,
LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, CLASS_DEF,
METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT,
INSTANCE_INIT" />
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="DOT" />
+ <property name="option" value="nl" />
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="COMMA" />
+ <property name="option" value="EOL" />
+ </module>
+ <module name="PackageName">
+ <property name="format"
value="^[a-z]+([.][a-z][a-zA-Z0-9]*)*$" />
+ </module>
+ <module name="MethodTypeParameterName">
+ <property name="format"
value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+ </module>
+ <module name="NonEmptyAtclauseDescription" />
+ <module name="JavadocMethod">
+ <property name="allowMissingParamTags" value="true" />
+ <property name="allowMissingReturnTag" value="true" />
+ <property name="allowedAnnotations"
value="Override,Test,BeforeClass,AfterClass,Before,After,BeforeAll,AfterAll,BeforeEach,AfterEach"
/>
+ </module>
+ <module name="MissingOverrideCheck" />
+ <!--Require braces for all control statements -->
+ <module name="NeedBraces" />
+ </module>
+ </module>
+ </checkstyleRules>
+ <violationSeverity>warning</violationSeverity>
+ <includeTestSourceDirectory>true</includeTestSourceDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>check-public-api</id>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ <configuration>
+ <checkstyleRules>
+ <module name="Checker">
+ <property name="charset" value="UTF-8" />
+ <property name="severity" value="warning" />
+ <module name="TreeWalker">
+ <module name="RegexpSinglelineJava">
+ <property name="format"
value="import\s+org[.]apache[.]accumulo[.](?!(core[.](client|data|iterators|security|spi)|minicluster|hadoop|classloader|start[.]spi[.]KeywordExecutable)[.;]).*"
/>
+ <property name="message" value="Found reference to
non-public Accumulo API" />
+ </module>
+ </module>
+ </module>
+ </checkstyleRules>
+ <violationSeverity>warning</violationSeverity>
+ <includeTestSourceDirectory>false</includeTestSourceDirectory>
+ </configuration>
</execution>
</executions>
</plugin>