diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 5f5d15a1..d70201b6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -163,10 +163,10 @@ jobs: - name: Copy build/report/tests/test for upload if: ${{ failure() }} working-directory: C:/ci.gradle - run: cp -r build/reports/tests/test D:/buildReports/${{runner.os}}/java${{matrix.java}}/${{matrix.RUNTIME}}-${{matrix.RUNTIME_VERSION}}/ + run: cp -r build/reports/tests/test D:/buildReports/${{runner.os}}/java${{matrix.java}}/${{matrix.RUNTIME}}-${{matrix.RUNTIME_VERSION}}/ - uses: actions/upload-artifact@v3 if: ${{ failure() }} with: name: buildReportsArtifactWindows path: D:/buildReports - retention-days: 3 \ No newline at end of file + retention-days: 3 diff --git a/src/main/groovy/io/openliberty/tools/gradle/extensions/FeatureExtension.groovy b/src/main/groovy/io/openliberty/tools/gradle/extensions/FeatureExtension.groovy index 1c8cdd24..d80357ab 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/extensions/FeatureExtension.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/extensions/FeatureExtension.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2014, 2019. + * (C) Copyright IBM Corporation 2014, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,9 @@ package io.openliberty.tools.gradle.extensions class FeatureExtension { - List name boolean acceptLicense = false String to String from + String verify = "enforce" } diff --git a/src/main/groovy/io/openliberty/tools/gradle/extensions/ServerExtension.groovy b/src/main/groovy/io/openliberty/tools/gradle/extensions/ServerExtension.groovy index 844ece3d..14182c8c 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/extensions/ServerExtension.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/extensions/ServerExtension.groovy @@ -1,5 +1,5 @@ /** - * (C) Copyright IBM Corporation 2017, 2020. + * (C) Copyright IBM Corporation 2017, 2023. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,7 @@ class ServerExtension { Properties env = new Properties() Properties var = new Properties() Properties defaultVar = new Properties() + Properties keys = new Properties() boolean clean = false String timeout diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy index b29d9ab5..3fee0d2e 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractFeatureTask.groovy @@ -23,6 +23,7 @@ import io.openliberty.tools.common.plugins.util.PluginExecutionException import io.openliberty.tools.common.plugins.util.PluginScenarioException import io.openliberty.tools.common.plugins.util.ServerFeatureUtil import io.openliberty.tools.gradle.utils.ArtifactDownloadUtil +import java.util.Map.Entry import org.gradle.api.Project import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Internal @@ -42,6 +43,7 @@ public class AbstractFeatureTask extends AbstractServerTask { private ServerFeatureUtil servUtil; + @Internal String jsonCoordinate; @@ -108,8 +110,8 @@ public class AbstractFeatureTask extends AbstractServerTask { } private class InstallFeatureTaskUtil extends InstallFeatureUtil { - public InstallFeatureTaskUtil(File installDir, File buildDir, String from, String to, Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons) throws PluginScenarioException, PluginExecutionException { - super(installDir, buildDir, from, to, pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons) + public InstallFeatureTaskUtil(File installDir, File buildDir, String from, String to, Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons, String verify, Collection> keyMap) throws PluginScenarioException, PluginExecutionException { + super(installDir, buildDir, from, to, pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons, verify, keyMap) setContainerEngine(this); } @@ -174,6 +176,11 @@ public class AbstractFeatureTask extends AbstractServerTask { } return ArtifactDownloadUtil.downloadArtifact(project, groupId, artifactId, type, version); } + + @Override + public File downloadSignature(File esa, String groupId, String artifactId, String type, String version) throws PluginExecutionException { + return ArtifactDownloadUtil.downloadSignature(project, groupId, artifactId, type, version, esa); + } } protected Set getPluginListedFeatures(boolean findEsaFiles) { @@ -239,6 +246,33 @@ public class AbstractFeatureTask extends AbstractServerTask { Set featuresToInstall = util.combineToSet(pluginListedFeatures, dependencyFeatures, serverFeatures) return featuresToInstall } + + /* + * + */ + @Internal + protected Collection> getKeyMap(){ + Collection> keyMapList = new ArrayList<>(); + if(server.keys == null) { + logger.debug("liberty.keys property map is empty") + return keyMapList; + + } + + Set> entries = server.keys.entrySet() + for (Entry entry : entries) { + Map keyMap = new HashMap<>(); + String key = (String) entry.getKey() + Object value = entry.getValue() + if (value != null) { + logger.debug("keyID : " + key + "\tkeyURL : " + value.toString()) + keyMap.put("keyid", key) + keyMap.put("keyurl", value.toString()) + } + keyMapList.add(keyMap) + } + return keyMapList; + } /** * Get a new instance of ServerFeatureUtil @@ -260,9 +294,10 @@ public class AbstractFeatureTask extends AbstractServerTask { return servUtil; } - private void createNewInstallFeatureUtil(Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons) throws PluginExecutionException { + private void createNewInstallFeatureUtil(Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons, Collection> keyMap) throws PluginExecutionException { try { - util = new InstallFeatureTaskUtil(getInstallDir(project), project.getBuildDir(), server.features.from, server.features.to, pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons) + logger.info("Feature signature verify option: " + server.features.verify) + util = new InstallFeatureTaskUtil(getInstallDir(project), project.getBuildDir(), server.features.from, server.features.to, pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons, server.features.verify, keyMap) } catch (PluginScenarioException e) { logger.debug("Exception received: " + e.getMessage(), (Throwable) e) logger.debug("Installing features from installUtility.") @@ -283,13 +318,14 @@ public class AbstractFeatureTask extends AbstractServerTask { openLibertyVersion = InstallFeatureUtil.getOpenLibertyVersion(propertiesList) } def additionalJsons = getAdditionalJsonList() - createNewInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVersion, containerName, additionalJsons) + Collection> keyMap = getKeyMap(); + createNewInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVersion, containerName, additionalJsons, keyMap) } return util; } - protected InstallFeatureUtil getInstallFeatureUtil(Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons) throws PluginExecutionException { - createNewInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons) + protected InstallFeatureUtil getInstallFeatureUtil(Set pluginListedEsas, List propertiesList, String openLibertyVerion, String containerName, List additionalJsons, Collection> keyMap) throws PluginExecutionException { + createNewInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVerion, containerName, additionalJsons, keyMap) return util } diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy index 59376f89..f3544509 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/AbstractServerTask.groovy @@ -60,7 +60,7 @@ abstract class AbstractServerTask extends AbstractLibertyTask { protected final String HEADER = "# Generated by liberty-gradle-plugin" - private static final String LIBERTY_CONFIG_GRADLE_PROPS = "(^liberty\\.server\\.(env|jvmOptions|bootstrapProperties|var|defaultVar))\\.(.+)" + private static final String LIBERTY_CONFIG_GRADLE_PROPS = "(^liberty\\.server\\.(env|jvmOptions|bootstrapProperties|var|defaultVar|keys))\\.(.+)" private static final Pattern pattern = Pattern.compile(LIBERTY_CONFIG_GRADLE_PROPS) protected final String PLUGIN_VARIABLE_CONFIG_OVERRIDES_XML = "configDropins/overrides/liberty-plugin-variable-config.xml" diff --git a/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallFeatureTask.groovy b/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallFeatureTask.groovy index f5deb0e1..fe158b86 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallFeatureTask.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/tasks/InstallFeatureTask.groovy @@ -17,6 +17,7 @@ package io.openliberty.tools.gradle.tasks import java.util.Set + import org.gradle.api.artifacts.ResolveException import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.TaskAction @@ -44,7 +45,7 @@ class InstallFeatureTask extends AbstractFeatureTask { } @TaskAction - void installFeature() { + void installFeature() throws PluginExecutionException { // If non-container mode, check for Beta version and skip if needed. Container mode does not need to check since featureUtility will check when it is called. def propertiesList = null; def openLibertyVersion = null; @@ -64,8 +65,9 @@ class InstallFeatureTask extends AbstractFeatureTask { } def pluginListedEsas = getPluginListedFeatures(true) - def additionalJsons = getAdditionalJsonList(); - InstallFeatureUtil util = getInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVersion, containerName, additionalJsons) + def additionalJsons = getAdditionalJsonList(); + def keyMap = getKeyMap(); + InstallFeatureUtil util = getInstallFeatureUtil(pluginListedEsas, propertiesList, openLibertyVersion, containerName, additionalJsons, keyMap) if(!pluginListedEsas.isEmpty() && isClosedLiberty) { installFeaturesFromAnt = true; diff --git a/src/main/groovy/io/openliberty/tools/gradle/utils/ArtifactDownloadUtil.groovy b/src/main/groovy/io/openliberty/tools/gradle/utils/ArtifactDownloadUtil.groovy index bfefc78f..5869b962 100644 --- a/src/main/groovy/io/openliberty/tools/gradle/utils/ArtifactDownloadUtil.groovy +++ b/src/main/groovy/io/openliberty/tools/gradle/utils/ArtifactDownloadUtil.groovy @@ -15,12 +15,13 @@ */ package io.openliberty.tools.gradle.utils +import org.apache.commons.io.FileUtils import org.gradle.api.Project import org.gradle.api.artifacts.ResolveException import io.openliberty.tools.common.plugins.util.PluginExecutionException +import org.gradle.internal.resolve.ArtifactNotFoundException public class ArtifactDownloadUtil { - public static File downloadArtifact(Project project, String groupId, String artifactId, String type, String version) throws PluginExecutionException { String coordinates = groupId + ":" + artifactId + ":" + version + "@" + type def dep = project.dependencies.create(coordinates) @@ -36,6 +37,20 @@ public class ArtifactDownloadUtil { return downloadFile(project, config, coordinates) } + + public static File downloadSignature(Project project, String groupId, String artifactId, String type, String version, File esa) throws PluginExecutionException { + String coordinates = groupId + ":" + artifactId + ":" + version + "@" + type + def dep = project.dependencies.create(coordinates) + def config = project.configurations.detachedConfiguration(dep) + def sig = downloadFile(project, config, coordinates); + //if signature and esa file are not in same directory, copy signature file to esa parent directory. + if (!sig.getParent().equals(esa.getParent())) { + project.getLogger().debug("Copying " + sig + " to " + esa.getAbsolutePath() + ".asc") + FileUtils.copyFile(sig, new File(esa.getAbsolutePath() + ".asc")) + } + return sig + + } private static File downloadFile(project, config, coordinates) { Set files = new HashSet() @@ -45,7 +60,7 @@ public class ArtifactDownloadUtil { files.add(artifactFile) project.getLogger().debug(artifactFile.toString()) } - } catch (ResolveException e) { + } catch (ResolveException | ArtifactNotFoundException e) { throw new PluginExecutionException("Could not find artifact with coordinates " + coordinates, e) } diff --git a/src/test/groovy/io/openliberty/tools/gradle/InstallFeature_single.groovy b/src/test/groovy/io/openliberty/tools/gradle/InstallFeature_single.groovy index 3e5a1e89..de9e587e 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/InstallFeature_single.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/InstallFeature_single.groovy @@ -2,6 +2,7 @@ package io.openliberty.tools.gradle import static org.junit.Assert.* +import org.junit.AfterClass import org.junit.BeforeClass import org.junit.FixMethodOrder import org.junit.Test @@ -21,6 +22,11 @@ class InstallFeature_single extends AbstractIntegrationTest{ createDir(buildDir) copySettingsFile(resourceDir, buildDir) } + + @AfterClass + public static void cleanup() { + deleteDir(new File(mavenLocalRepo, "test/user/test/osgi")); + } @Test public void test_installFeature_single() { @@ -57,4 +63,6 @@ class InstallFeature_single extends AbstractIntegrationTest{ runTasks(buildDir, 'installFeature') assert simpleFile.exists() : "test.user.test.osgi.SimpleActivator.mf is not installed" } + + } diff --git a/src/test/groovy/io/openliberty/tools/gradle/PrepareFeatureTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/PrepareFeatureTest.groovy index 4eed5849..3c4a2a7c 100644 --- a/src/test/groovy/io/openliberty/tools/gradle/PrepareFeatureTest.groovy +++ b/src/test/groovy/io/openliberty/tools/gradle/PrepareFeatureTest.groovy @@ -2,7 +2,7 @@ package io.openliberty.tools.gradle import static org.junit.Assert.* -import org.junit.Before +import org.junit.BeforeClass import org.junit.AfterClass import org.junit.FixMethodOrder import org.junit.Test @@ -38,8 +38,8 @@ class PrepareFeatureTest extends AbstractIntegrationTest{ } - @Before - public void setup() { + @BeforeClass + public static void setup() { org.junit.Assume.assumeTrue(checkOpenLibertyVersion()); createDir(buildDirSingle) createDir(buildDirMultiple) @@ -51,7 +51,6 @@ class PrepareFeatureTest extends AbstractIntegrationTest{ copyFile(resourceHelloEsa, helloEsa) copyFile(resourceSimpleBom, simpleBom) copyFile(resourceSimpleEsa, simpleEsa) - } @@ -115,5 +114,6 @@ class PrepareFeatureTest extends AbstractIntegrationTest{ throw new AssertionError ("Fail to install multiple user features.", e) } } + } diff --git a/src/test/groovy/io/openliberty/tools/gradle/VerifyFeatureTest.groovy b/src/test/groovy/io/openliberty/tools/gradle/VerifyFeatureTest.groovy new file mode 100644 index 00000000..d9267a43 --- /dev/null +++ b/src/test/groovy/io/openliberty/tools/gradle/VerifyFeatureTest.groovy @@ -0,0 +1,126 @@ +package io.openliberty.tools.gradle + +import static org.junit.Assert.* + +import org.junit.BeforeClass +import org.junit.After +import org.junit.AfterClass +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runners.MethodSorters +import io.openliberty.tools.common.plugins.util.PluginExecutionException +import org.gradle.testkit.runner.BuildResult + +class VerifyFeatureTest extends AbstractIntegrationTest{ + static File resourceDir = new File("build/resources/test/prepare-feature-test") + static File resourceDir2 = new File("build/resources/test/verify-feature-test") + static File buildDir = new File(integTestDir, "/VerifyFeature") + static File resourceSimpleBom = new File(resourceDir, "SimpleActivator-bom-1.0.pom") + static File resourceSimpleEsa = new File(resourceDir, "SimpleActivatorESA-1.0.esa") + static File resourceSimpleAsc = new File(resourceDir, "SimpleActivatorESA-1.0.esa.asc") + static File mavenLocalRepo = new File(System.getProperty("user.home")+ "/.m2/repository") + static File userTestRepo = new File(mavenLocalRepo, "test/user/test/osgi") + static File simpleBom = new File(userTestRepo, "SimpleActivator-bom/1.0/SimpleActivator-bom-1.0.pom") + static File simpleEsa = new File(userTestRepo, "SimpleActivatorESA/1.0/SimpleActivatorESA-1.0.esa") + static File simpleAsc = new File(userTestRepo, "SimpleActivatorESA/1.0/SimpleActivatorESA-1.0.esa.asc") + static File simpleValidKey = new File(buildDir, "src/test/resources/SimpleActivatorValidKey.asc") + def featureFile = new File(buildDir, "build/wlp/usr/extension/lib/features/test.user.test.osgi.SimpleActivator.mf") + + + @BeforeClass + public static void setup() { + createDir(buildDir) + createTestProject(buildDir, resourceDir2, "build.gradle") + copyFile(resourceSimpleBom, simpleBom) + copyFile(resourceSimpleEsa, simpleEsa) + copyFile(resourceSimpleAsc, simpleAsc) + } + + @After + public void cleanup() { + featureFile.delete() + } + + + @Test + public void test_verifyEnforce() { + try { + System.properties['verify'] = 'enforce' + System.properties['keyid'] = '' + runTasks(buildDir, 'installFeature') + + assert featureFile.exists() : "SimpleActivator.mf cannot be generated" + + } catch (Exception e) { + throw new AssertionError ("Verify \"enforce\" should pass", e) + } + } + + + + //TODO: Disable for now. +// @Test +// public void test_verifyALL() { +// try { +// System.properties['verify'] = 'all' +// System.properties['keyid'] = '0x05534365803788CE' +// assert simpleValidKey.exists() : "no valid key" +// +// runTasks(buildDir, 'installFeature') +// +// assert featureFile.exists() : "SimpleActivator.mf cannot be generated" +// +// } catch (Exception e) { +// throw new AssertionError ("Fail to verify user feature.", e) +// } +// } + + @Test + public void test_verifyALLWrongKeyId() { + boolean testPassed = false; + System.properties['verify'] = 'all' + System.properties['keyid'] = '0xWRONGKEY' + + try{ + runTasks(buildDir, 'installFeature') + }catch (Exception e) { + testPassed = true; + } + + assert testPassed == true : "Verify \"all\" with wrong key id should fail" + } + + @Test + public void test_verifyWARN() { + try { + println(featureFile.getAbsolutePath()) + System.properties['verify'] = 'warn' + System.properties['keyid'] = '0xWRONGKEY' + + runTasks(buildDir, 'installFeature') + + assert featureFile.exists() : "SimpleActivator.mf cannot be generated" + + } catch (Exception e) { + throw new AssertionError ("Verify \"warn\" with wrong key id should install the feature, but print warning message", e) + } + } + + @Test + public void test_verifySkip() { + try { + println(featureFile.getAbsolutePath()) + System.properties['verify'] = 'skip' + System.properties['keyid'] = '0xWRONGKEY' + + runTasks(buildDir, 'installFeature') + + assert featureFile.exists() : "SimpleActivator.mf cannot be generated" + + } catch (Exception e) { + throw new AssertionError ("Verify \"skip\" with wrong key id should install the feature, but print warning message", e) + } + } + + +} diff --git a/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa b/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa index 2e619719..635d0715 100644 Binary files a/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa and b/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa differ diff --git a/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa.asc b/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa.asc new file mode 100644 index 00000000..e2886868 --- /dev/null +++ b/src/test/resources/prepare-feature-test/SimpleActivatorESA-1.0.esa.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- + +iHUEABYKAB0WIQTZfjfdN9icDzpsd5oFU0NlgDeIzgUCYuXWWgAKCRAFU0NlgDeI +zoQoAP9Ml57juXFOVpqNljeLKEZ+OfDsLs5QJbZJ2JbXF+d7zwEAm1QDQaTRy4Kl +tghBIFPUgTSrKl0U39pMpje5xvvVpgM= +=1Xtn +-----END PGP SIGNATURE----- diff --git a/src/test/resources/verify-feature-test/build.gradle b/src/test/resources/verify-feature-test/build.gradle new file mode 100644 index 00000000..5eb55a94 --- /dev/null +++ b/src/test/resources/verify-feature-test/build.gradle @@ -0,0 +1,44 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + maven { + name = 'Sonatype Nexus Snapshots' + url = 'https://oss.sonatype.org/content/repositories/snapshots/' + } + } + dependencies { + classpath "io.openliberty.tools:liberty-gradle-plugin:$lgpVersion" + } +} + +apply plugin: 'liberty' + +repositories { + mavenCentral() + mavenLocal() { + metadataSources { + mavenPom() + artifact() + } + } +} + +dependencies { + featuresBom 'test.user.test.osgi:SimpleActivator-bom:1.0' +} + +def keyid = System.properties['keyid'] +def keyurl = file("src/test/resources/SimpleActivatorValidKey.asc") +liberty { + server{ + name = 'LibertyProjectServer' + serverXmlFile = file("src/test/resources/server.xml") + keys."$keyid" = "$keyurl" + features { + name = ["SimpleActivator-1.0"] + acceptLicense = true + verify = System.properties['verify'] + } + } +} diff --git a/src/test/resources/verify-feature-test/settings.gradle b/src/test/resources/verify-feature-test/settings.gradle new file mode 100644 index 00000000..c2d3edc1 --- /dev/null +++ b/src/test/resources/verify-feature-test/settings.gradle @@ -0,0 +1 @@ +//Empty \ No newline at end of file diff --git a/src/test/resources/verify-feature-test/src/test/resources/SimpleActivatorValidKey.asc b/src/test/resources/verify-feature-test/src/test/resources/SimpleActivatorValidKey.asc new file mode 100644 index 00000000..fab966a1 --- /dev/null +++ b/src/test/resources/verify-feature-test/src/test/resources/SimpleActivatorValidKey.asc @@ -0,0 +1,15 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Comment: Hostname: +Version: Hockeypuck 2.1.0-223-gdc2762b + +xjMEYryhzxYJKwYBBAHaRw8BAQdAr/PgyIUi11nwm9t1hb5hPXV2C+fMFex0wQ1e +dnR7IEXNHVNhcmFoIExpbSA8aml3b28ubGltQGlibS5jb20+wpoEExYKAEIWIQTZ +fjfdN9icDzpsd5oFU0NlgDeIzgUCYryhzwIbAwUJA8JnAAULCQgHAgMiAgEGFQoJ +CAsCBBYCAwECHgcCF4AACgkQBVNDZYA3iM4zpwEAk/GjVbe1Nh6Sdgz6Bz7m7Ri8 +PTOm83nJbLQ58wiQjLIBAPROmPtM2GZtZpXnLvcTQZ1LMagtO8bf2Lrmwr4sSecE +zjgEYryhzxIKKwYBBAGXVQEFAQEHQO6uNNAomeS4cvSOOiF8TZp57y3srA0jQCTM +4FgyA4EeAwEIB8J+BBgWCgAmFiEE2X433TfYnA86bHeaBVNDZYA3iM4FAmK8oc8C +GwwFCQPCZwAACgkQBVNDZYA3iM5QsQEA9wCJkczk0UicmUhI+yywuTuh5MF3csdD +fyUL++G/Co0A/19f4kf/LVLh+EfsGRHU256OI8RWd9JUR8O2M/HSJ8sK +=JYSd +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/test/resources/verify-feature-test/src/test/resources/server.xml b/src/test/resources/verify-feature-test/src/test/resources/server.xml new file mode 100644 index 00000000..2787aa84 --- /dev/null +++ b/src/test/resources/verify-feature-test/src/test/resources/server.xml @@ -0,0 +1,9 @@ + + + + json-1.0 + + + +