diff --git a/.gitignore b/.gitignore index 51e3a15..05955b4 100644 --- a/.gitignore +++ b/.gitignore @@ -85,3 +85,4 @@ node_modules/ *.iml /gradle.properties +/.idea/ diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..4f8d28d --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,108 @@ +import com.cognifide.gradle.aem.bundle.tasks.bundle + +plugins { + java + `maven-publish` + alias(libs.plugins.gap.bundle) + alias(libs.plugins.gap.pkg) + alias(libs.plugins.nebula) + alias(libs.plugins.quality) + alias(libs.plugins.cpd) + alias(libs.plugins.node) +} + +group = "com.swisscom.aem.tools" + +defaultTasks("check") + +quality { + checkstyleVersion = libs.versions.checkstyle.get() + pmdVersion = libs.versions.pmd.get() + spotbugsVersion = libs.versions.spotbugs.get() + spotbugsEffort = "max" // min, less, more or max + spotbugsLevel = "low" // low, medium, high +} + +afterEvaluate { + tasks.named("check") { + dependsOn("checkQualityMain") + } + + dependencies { + add("spotbugsPlugins", libs.findsecbugs) + add("spotbugsPlugins", libs.sbContrib) + add("pmd", libs.pmd.ant) + add("pmd", libs.pmd.java) + + // Spotbugs runtime annotations + add("compileOnly", libs.spotbugs.annotations) + } +} + +tasks { + withType { + options.encoding = "UTF-8" + options.compilerArgs.add("-Xlint:all") + options.compilerArgs.add("-Xlint:-processing") + options.compilerArgs.add("-Xlint:-serial") + options.compilerArgs.add("-Werror") + } + + test { + useJUnitPlatform() + } + + javadoc { + options.encoding = "UTF-8" + } +} + +java { + afterEvaluate { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + + dependencies { + // Lombok + annotationProcessor(libs.lombok) + compileOnly(libs.lombok) + + // AEM + compileOnly(libs.servlet) + compileOnly(libs.gson) + compileOnly(libs.apacheCommons.lang3) + compileOnly(libs.osgi.cmpn) + compileOnly(libs.jcr) + compileOnly(libs.spiCommons) + compileOnly(libs.sling.api) + compileOnly(libs.sling.annotations) + + // Test framework + testImplementation(libs.junit) + testImplementation(libs.aemMock) + } +} + +node { + version.set(libs.versions.node.get()) + npmVersion.set(libs.versions.npm.get()) + npmInstallCommand.set("ci") + download.set(true) +} + +aem { + bundleEmbed(libs.apacheCommons.jexl, "org.apache.commons.jexl3.*", export = false) + + tasks { + packageCompose { + + } + + withType { + bundle { + javaPackage.set("${project.group}.jcrhopper") + } + } + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index d2ffc37..589bdcf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,4 +6,4 @@ dependencyResolutionManagement { } } -rootProject.name = "JCR Hopper" +rootProject.name = "jcr-hopper" diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/api/PortalScriptContext.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/api/PortalScriptContext.java index f76a6af..8c896c9 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/api/PortalScriptContext.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/api/PortalScriptContext.java @@ -4,8 +4,6 @@ import org.apache.sling.api.request.RequestParameterMap; import org.apache.sling.api.resource.ResourceResolver; -import com.day.cq.wcm.api.PageManager; - /** * The context for all portal scripts. * @@ -66,11 +64,4 @@ public interface PortalScriptContext { * @return Resource Resolver */ ResourceResolver getResourceResolver(); - - /** - * Returns the page manager which is attached with the current session. - * - * @return PageManager - */ - PageManager getPageManager(); } diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/AbstractPortalScript.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/AbstractPortalScript.java index 9f851df..a4298bb 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/AbstractPortalScript.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/AbstractPortalScript.java @@ -2,6 +2,7 @@ import java.io.PrintWriter; import java.util.Arrays; +import java.util.HashSet; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -13,7 +14,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.resource.ResourceResolver; -import com.google.common.collect.Sets; import com.swisscom.aem.tools.jcrhopper.MyTask; import com.swisscom.aem.tools.jcrhopper.api.PortalScript; import com.swisscom.aem.tools.jcrhopper.api.PortalScriptContext; @@ -26,7 +26,8 @@ public abstract class AbstractPortalScript implements PortalScript, PortalScript public static final String PARAMETER_DRY_RUN = "dryRun"; private static final int DEFAULT_MAX_DURATION_IN_SECONDS = 60; - private static final Set VALID_DRY_RUN_VALUES = Sets.newHashSet("true", "false", "on", "off"); + private static final Set VALID_DRY_RUN_VALUES = new HashSet<>(Arrays.asList("true", "false", "on", "off")); + private static final Set IGNORED_SYSTEM_QUERY_PARAMS = new HashSet<>(Arrays.asList("run", "submit", ":cq_csrf_token")); @Getter(AccessLevel.PROTECTED) private final PortalScriptContext context; @@ -86,7 +87,8 @@ public void process() throws Exception { logParameters(); checkDryRunValue(); doProcess(); - } finally { + } + finally { MyTask.unregisterTaskName(); // Note: Risky function (MyTask.resetCancellation()) as a second task with the same class name may exist, // instead of the intended task. But we accept that, as we assume that only one @@ -100,10 +102,9 @@ public void process() throws Exception { } private void logParameters() { - final Set ignoreParameters = Sets.newHashSet("run", "submit", ":cq_csrf_token"); context.getParameters().entrySet() .stream() - .filter(e -> !ignoreParameters.contains(e.getKey())) + .filter(e -> !IGNORED_SYSTEM_QUERY_PARAMS.contains(e.getKey())) .forEach(e -> info("Parameter %s: %s", e.getKey(), Arrays.toString(e.getValue()))); } diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/DefaultPortalScriptContext.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/DefaultPortalScriptContext.java index d1ca061..d2cd680 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/DefaultPortalScriptContext.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/DefaultPortalScriptContext.java @@ -2,9 +2,6 @@ import java.io.PrintWriter; -import com.swisscom.aem.tools.jcrhopper.api.PortalScriptContext; -import com.swisscom.aem.tools.jcrhopper.api.PortalScriptOutputWriter; - import lombok.Getter; import org.apache.sling.api.SlingHttpServletRequest; @@ -12,11 +9,11 @@ import org.apache.sling.api.request.RequestParameterMap; import org.apache.sling.api.resource.ResourceResolver; -import com.day.cq.wcm.api.PageManager; +import com.swisscom.aem.tools.jcrhopper.api.PortalScriptContext; +import com.swisscom.aem.tools.jcrhopper.api.PortalScriptOutputWriter; /** * Default portal script context configuration. - * */ public class DefaultPortalScriptContext implements PortalScriptContext { @@ -25,9 +22,6 @@ public class DefaultPortalScriptContext implements PortalScriptContext { private final SlingHttpServletRequest request; - @Getter - private final PageManager pageManager; - /** * Creates a new portal script context with a servlet request as input and a writer for the output. * @@ -38,7 +32,6 @@ public DefaultPortalScriptContext(SlingHttpServletRequest request, PrintWriter w this.request = request; final LogLevel logLevel = LogLevel.fromString(request.getParameter("log")); this.outputWriter = new DefaultPortalScriptOutput(writer, logLevel); - pageManager = getResourceResolver().adaptTo(PageManager.class); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/PortalScriptServlet.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/PortalScriptServlet.java index d20decc..362426a 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/PortalScriptServlet.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/impl/PortalScriptServlet.java @@ -43,7 +43,8 @@ protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse if (isAbort(request)) { handleAbort(context); - } else { + } + else { executeOnetimerScript(response, context); } } @@ -75,7 +76,8 @@ private void executeOnetimerScript(SlingHttpServletResponse response, PortalScri final long duration = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS); context.getOutputWriter().info("Successfully finished %s in %sms", SCRIPT_NAME, duration); - } catch (Exception e) { + } + catch (Exception e) { logException(context, e); } } diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/DerivedMap.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/DerivedMap.java index 51be2ae..7adad83 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/DerivedMap.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/DerivedMap.java @@ -3,6 +3,7 @@ import java.util.AbstractMap; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -10,8 +11,6 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; -import com.google.common.collect.Sets; - @RequiredArgsConstructor public class DerivedMap implements Map { @NonNull @@ -78,7 +77,10 @@ public void clear() { @Override public Set keySet() { - return Sets.union(backing.keySet(), local.keySet()); + final Set result = new HashSet<>(); + result.addAll(backing.keySet()); + result.addAll(local.keySet()); + return result; } @Override diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/JcrFunctions.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/JcrFunctions.java index 371c5d3..3e2b91c 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/JcrFunctions.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/JcrFunctions.java @@ -1,9 +1,11 @@ package com.swisscom.aem.tools.jcrhopper.pipeline; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Array; import java.math.BigDecimal; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Calendar; import java.util.List; @@ -20,7 +22,6 @@ import lombok.RequiredArgsConstructor; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; @RequiredArgsConstructor @@ -40,27 +41,27 @@ private static Object objectFromValue(Value val, int type) throws RepositoryExce final Object result; switch (type) { - case PropertyType.BOOLEAN: - result = val.getBoolean(); - break; - case PropertyType.DATE: - result = val.getDate(); - break; - case PropertyType.DECIMAL: - result = val.getDecimal(); - break; - case PropertyType.DOUBLE: - result = val.getDouble(); - break; - case PropertyType.LONG: - result = val.getLong(); - break; - case PropertyType.BINARY: - result = val.getBinary(); - break; - default: - result = val.getString(); - break; + case PropertyType.BOOLEAN: + result = val.getBoolean(); + break; + case PropertyType.DATE: + result = val.getDate(); + break; + case PropertyType.DECIMAL: + result = val.getDecimal(); + break; + case PropertyType.DOUBLE: + result = val.getDouble(); + break; + case PropertyType.LONG: + result = val.getLong(); + break; + case PropertyType.BINARY: + result = val.getBinary(); + break; + default: + result = val.getString(); + break; } return result; @@ -243,7 +244,9 @@ public Node resolve(String path) throws RepositoryException { * @throws IOException If the encoding is invalid */ public Binary toBinary(String data, String encoding) throws RepositoryException, IOException { - return session.getValueFactory().createBinary(IOUtils.toInputStream(data, encoding)); + return session.getValueFactory().createBinary( + new ByteArrayInputStream(data.getBytes(Charset.forName(encoding))) + ); } /** @@ -283,29 +286,41 @@ public Value valueFromObject(Object value) throws RepositoryException { private Value convertToValue(ValueFactory fac, Object value) throws RepositoryException { if (value instanceof String) { return fac.createValue((String) value); - } else if (value instanceof Integer) { + } + else if (value instanceof Integer) { return fac.createValue((Integer) value); - } else if (value instanceof Float) { + } + else if (value instanceof Float) { return fac.createValue((Float) value); - } else if (value instanceof Byte) { + } + else if (value instanceof Byte) { return fac.createValue((Byte) value); - } else if (value instanceof BigDecimal) { + } + else if (value instanceof BigDecimal) { return fac.createValue((BigDecimal) value); - } else if (value instanceof Node) { + } + else if (value instanceof Node) { return fac.createValue((Node) value); - } else if (value instanceof Calendar) { + } + else if (value instanceof Calendar) { return fac.createValue((Calendar) value); - } else if (value instanceof Boolean) { + } + else if (value instanceof Boolean) { return fac.createValue((Boolean) value); - } else if (value instanceof Double) { + } + else if (value instanceof Double) { return fac.createValue((Double) value); - } else if (value instanceof Long) { + } + else if (value instanceof Long) { return fac.createValue((Long) value); - } else if (value instanceof Binary) { + } + else if (value instanceof Binary) { return fac.createValue((Binary) value); - } else if (value instanceof InputStream) { + } + else if (value instanceof InputStream) { return fac.createValue(fac.createBinary((InputStream) value)); - } else { + } + else { return fac.createValue(value.toString()); } } @@ -392,17 +407,23 @@ public Object asValueType(Object value) throws RepositoryException { if (value instanceof Value) { result = value; - } else if (value instanceof Value[]) { + } + else if (value instanceof Value[]) { result = value; - } else if (value instanceof Property && ((Property) value).isMultiple()) { + } + else if (value instanceof Property && ((Property) value).isMultiple()) { result = ((Property) value).getValues(); - } else if (value instanceof Property) { + } + else if (value instanceof Property) { result = ((Property) value).getValue(); - } else if (value instanceof List) { + } + else if (value instanceof List) { result = valuesFromList((List) value); - } else if (value.getClass().isArray()) { + } + else if (value.getClass().isArray()) { result = valuesFromArray(value); - } else { + } + else { result = valueFromObject(value); } diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/PipelineContext.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/PipelineContext.java index 87908a3..726c2a4 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/PipelineContext.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/PipelineContext.java @@ -11,7 +11,6 @@ import lombok.Getter; -import org.apache.commons.io.IOUtils; import org.apache.commons.jexl3.JexlBuilder; import org.apache.commons.jexl3.JexlEngine; import org.apache.commons.jexl3.JxltEngine; @@ -69,7 +68,6 @@ public PipelineContext( executor = new ElExecutorImpl(engine, templateEngine); executor.registerFunctions("jcr", jcrFunctions); executor.registerFunctions("req", requestParams); - executor.registerFunctions("io", IOUtils.class); executor.registerFunctions("str", StringUtils.class); executor.registerFunctions("arr", ArrayUtils.class); executor.registerFunctions("arrays", Arrays.class); diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/CreateChildNodeConfig.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/CreateChildNodeConfig.java index 8a1a973..2f15bad 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/CreateChildNodeConfig.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/CreateChildNodeConfig.java @@ -8,7 +8,8 @@ import lombok.NonNull; import lombok.experimental.Accessors; -import com.day.cq.commons.jcr.JcrConstants; +import org.apache.jackrabbit.JcrConstants; + import com.swisscom.aem.tools.jcrhopper.pipeline.Action; import com.swisscom.aem.tools.jcrhopper.pipeline.ConflictResolution; diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/RenameProperty.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/RenameProperty.java index 81e4e85..8b8c8ec 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/RenameProperty.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/RenameProperty.java @@ -60,7 +60,7 @@ private boolean shouldStopOnConflict( if (node.hasProperty(newName)) { final Property existing = node.getProperty(newName); switch (config.conflict()) { - case ConflictResolution.THROW: + case THROW: throw new PipelineException( String.format( "Property %s could not be renamed to %s because it already exists on %s", @@ -69,10 +69,10 @@ private boolean shouldStopOnConflict( node.getPath() ) ); - case ConflictResolution.IGNORE: + case IGNORE: context.info("Not replacing existing property {} on {} with value from {}", newName, node.getPath(), propertyName); return true; - case ConflictResolution.FORCE: + case FORCE: context.info("Replacing existing property {} on {} with value from {}", newName, node.getPath(), propertyName); existing.remove(); return true; @@ -87,7 +87,7 @@ private boolean shouldStopOnMissingProperty( Node node, PipelineContext context, String propertyName, String newName) throws RepositoryException, PipelineException { if (!node.hasProperty(propertyName)) { switch (config.doesNotExist()) { - case ConflictResolution.THROW: + case THROW: throw new PipelineException( String.format( "Property %s on %s could not be found", @@ -95,7 +95,7 @@ private boolean shouldStopOnMissingProperty( newName ) ); - case ConflictResolution.IGNORE: + case IGNORE: context.warn("Property {} on {} does not exist. Set doesNotExist to “force” to avoid this warning", propertyName, node.getPath()); return true; diff --git a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/ReorderNode.java b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/ReorderNode.java index b9a2aff..20b5a39 100644 --- a/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/ReorderNode.java +++ b/src/main/java/com/swisscom/aem/tools/jcrhopper/pipeline/actions/ReorderNode.java @@ -40,14 +40,14 @@ public void run(Node node, Map vars, PipelineContext context) th context.info("Moving {} before {} in list of child nodes of {}", node.getName(), beforeNodeName, parent.getPath()); } else { switch (config.conflict()) { - case ConflictResolution.IGNORE: + case IGNORE: context.warn( "Could not find child node {} of {}. Set conflict to “force” to get rid of this warning.", beforeNodeName, parent.getPath() ); return; - case ConflictResolution.THROW: + case THROW: throw new PipelineException(String.format( "Could not find child node %s of %s", beforeNodeName, diff --git a/versions.toml b/versions.toml index dbe4625..288b831 100644 --- a/versions.toml +++ b/versions.toml @@ -7,58 +7,25 @@ spotbugs = "4.8.6" node = "20.11.0" npm = "10.2.3" junit = "5.4.1" -slf4j = "1.7.25" +jackrabbit = "2.18.3" [libraries] osgi-cmpn = { group = "org.osgi", name = "osgi.cmpn", version.ref = "osgi" } -osgi-annotation = { group = "org.osgi", name = "osgi.annotation", version.ref = "osgi" } # Java & AEM dependencies lombok = "org.projectlombok:lombok:1.18.30" -junit-api = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } -junit-impl = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } -junit-platform = "org.junit.platform:junit-platform-launcher:1.11.0" +junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit" } aemMock = "io.wcm:io.wcm.testing.aem-mock.junit5:4.1.4" -slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" } -slf4j-api = { group = "org.slf4j", name = "slf4j-api", version.ref = "slf4j" } -commonsIo = "commons-io:commons-io:2.13.0" -jsoup = "org.jsoup:jsoup:1.13.1" -# FIXME: Why 6.0.0 and not 7.0.0 like cmpn and annotation -osgi-core = "org.osgi:org.osgi.core:6.0.0" -osgi-serviceComponent = "org.osgi:org.osgi.service.component:1.4.0" -osgi-annotationVersioning = "org.osgi:org.osgi.annotation.versioning:1.1.0" -osgi-serviceMetatypeAnnotations = "org.osgi:org.osgi.service.metatype.annotations:1.4.0" -osgi-annotationBundle = "org.osgi:org.osgi.annotation.bundle:1.0.0" +spiCommons = { group = "org.apache.jackrabbit", name = "jackrabbit-spi-commons", version.ref = "jackrabbit" } servlet = "javax.servlet:javax.servlet-api:3.1.0" -jsp = "javax.servlet.jsp:jsp-api:2.0" jcr = "javax.jcr:jcr:2.0" -geronimo = "org.apache.geronimo.specs:geronimo-atinject_1.0_spec:1.0" sling-api = "org.apache.sling:org.apache.sling.api:2.16.4" -sling-jcr = "org.apache.sling:org.apache.sling.jcr.api:2.4.0" -sling-junit-core = "org.apache.sling:org.apache.sling.junit.core:1.0.8" -sling-junit-scriptable = "org.apache.sling:org.apache.sling.junit.scriptable:1.0.12" -sling-junit-remote = "org.apache.sling:org.apache.sling.junit.remote:1.0.8" -sling-testingTools = "org.apache.sling:org.apache.sling.testing.tools:1.0.8" -sling-servletsPost = "org.apache.sling:org.apache.sling.servlets.post:2.3.4" -sling-models = "org.apache.sling:org.apache.sling.models.api:1.3.6" -sling-settings = "org.apache.sling:org.apache.sling.settings:1.3.8" sling-annotations = "org.apache.sling:org.apache.sling.servlets.annotations:1.2.6" -sling-mock = "org.apache.sling:org.apache.sling.testing.sling-mock-oak:3.1.2-1.40.0" -sling-json = "org.apache.sling:org.apache.sling.commons.json:2.0.6" -sling-launchpad = "org.apache.sling:org.apache.sling.launchpad:6" -aemCoreComponents-lib = { group = "com.adobe.cq", name = "core.wcm.components.core", version.ref = "aemCoreComponents" } -guava = "com.google.guava:guava:15.0" -jodaTime = "joda-time:joda-time:2.9.1" -brightcove-api = "com.coresecure.brightcove.cq5:brightcove-services:4.1.1-SNAPSHOT" -acsCommons-lib = { group = "com.adobe.acs", name = "acs-aem-commons-bundle", version.ref = "acsCommons" } -aemUberJar = "com.adobe.aem:uber-jar:6.5.21" -integrationClient = "ch.swisscom.integration:client:2024.9.1" -wiremock = "org.wiremock:wiremock-standalone:3.9.1" -mockito = "org.mockito:mockito-junit-jupiter:3.3.3" -swagger = "io.swagger.core.v3:swagger-annotations:2.1.13" +apacheCommons-lang3 = "org.apache.commons:commons-lang3:3.6" +gson = "com.google.code.gson:gson:2.8.9" # Bundled dependencies -jexl = "org.apache.commons:commons-jexl3:3.4.0" +apacheCommons-jexl = "org.apache.commons:commons-jexl3:3.1" # Quality plugin dependencies findsecbugs = "com.h3xstream.findsecbugs:findsecbugs-plugin:1.13.0"