blob: 64c1d530d61e9847cc8a410729c6b442cf987827 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.itest.springboot.util;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.camel.itest.springboot.ITestConfig;
import org.apache.camel.itest.springboot.ITestConfigBuilder;
import org.apache.camel.itest.springboot.arquillian.SpringBootZipExporterImpl;
import org.apache.commons.io.IOUtils;
import org.jboss.arquillian.container.se.api.ClassPath;
import org.jboss.arquillian.core.spi.InvocationException;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ArchivePath;
import org.jboss.shrinkwrap.api.Configuration;
import org.jboss.shrinkwrap.api.ConfigurationBuilder;
import org.jboss.shrinkwrap.api.Domain;
import org.jboss.shrinkwrap.api.ExtensionLoader;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.Asset;
import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
import org.jboss.shrinkwrap.api.asset.FileAsset;
import org.jboss.shrinkwrap.api.exporter.ZipExporter;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.jboss.shrinkwrap.impl.base.ServiceExtensionLoader;
import org.jboss.shrinkwrap.impl.base.URLPackageScanner;
import org.jboss.shrinkwrap.impl.base.asset.AssetUtil;
import org.jboss.shrinkwrap.impl.base.path.BasicPath;
import org.jboss.shrinkwrap.resolver.api.maven.ConfigurableMavenResolverSystem;
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact;
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinate;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenCoordinates;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencies;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependency;
import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencyExclusion;
/**
* Packages a module in a spring-boot compatible nested-jar structure.
*/
public final class ArquillianPackager {
/**
* A flag to enable system-out logging.
* Cannot use logging libraries here.
*/
private static final boolean DEBUG_ENABLED = false;
/**
* Configuration of the library checker.
*/
private static final boolean FAIL_ON_TEST_LIBRARY_MISMATCH = false;
private static final boolean FAIL_ON_RELATED_LIBRARY_MISMATCH = true;
private static final boolean VERSION_EQUALITY_MINOR_VERSION = true;
/**
* Spring-boot 1.4+ packaging model
*/
private static final String LIB_FOLDER = "/BOOT-INF/lib";
private static final String CLASSES_FOLDER = "BOOT-INF/classes";
private static final Pattern PROP_PATTERN = Pattern.compile("(\\$\\{[^}]*\\})");
private ArquillianPackager() {
}
public static Archive<?> springBootPackage(ITestConfig config) throws Exception {
if (!new File(".").getCanonicalFile().getName().equals("camel-itest-spring-boot")) {
throw new IllegalStateException("In order to run the integration tests, 'camel-itest-spring-boot' must be the working directory. Check your configuration.");
}
ExtensionLoader extensionLoader = new ServiceExtensionLoader(Collections.singleton(getExtensionClassloader()));
extensionLoader.addOverride(ZipExporter.class, SpringBootZipExporterImpl.class);
ConfigurationBuilder builder = new ConfigurationBuilder().extensionLoader(extensionLoader);
Configuration conf = builder.build();
Domain domain = ShrinkWrap.createDomain(conf);
JavaArchive ark = domain.getArchiveFactory().create(JavaArchive.class, "test.jar");
ark = ark.addAsManifestResource("BOOT-MANIFEST.MF", "MANIFEST.MF");
ark = ark.addAsDirectories(LIB_FOLDER);
if (!CLASSES_FOLDER.equals("")) {
ark = ark.addAsDirectories(CLASSES_FOLDER);
}
if (config.getUseCustomLog()) {
ark = ark.addAsResource("spring-logback.xml", CLASSES_FOLDER + "/spring-logback.xml");
}
for (Map.Entry<String, String> res : config.getResources().entrySet()) {
ark = ark.addAsResource(res.getKey(), CLASSES_FOLDER + "/" + res.getValue());
}
String version = System.getProperty("version_org.apache.camel:camel-core");
if (version == null) {
config.getMavenVersion();
}
if (version == null) {
// It is missing when launching from IDE
PomEquippedResolveStage pom = resolver(config).loadPomFromFile("pom.xml");
List<MavenResolvedArtifact> resolved = Arrays.asList(pom.importCompileAndRuntimeDependencies().resolve().withoutTransitivity().asResolvedArtifact());
for (MavenResolvedArtifact dep : resolved) {
if (dep.getCoordinate().getGroupId().equals("org.apache.camel.springboot")) {
version = dep.getCoordinate().getVersion();
break;
}
}
}
debug("Resolved version: " + version);
if (version == null) {
throw new IllegalStateException("Cannot determine the current version of the camel component");
}
List<MavenDependencyExclusion> commonExclusions = new LinkedList<>();
commonExclusions.add(MavenDependencies.createExclusion("commons-logging", "commons-logging"));
commonExclusions.add(MavenDependencies.createExclusion("org.slf4j", "slf4j-log4j12"));
commonExclusions.add(MavenDependencies.createExclusion("log4j", "log4j"));
commonExclusions.add(MavenDependencies.createExclusion("log4j", "log4j-slf4j-impl"));
commonExclusions.add(MavenDependencies.createExclusion("org.apache.logging.log4j", "log4j"));
commonExclusions.add(MavenDependencies.createExclusion("org.apache.logging.log4j", "log4j-core"));
commonExclusions.add(MavenDependencies.createExclusion("org.apache.logging.log4j", "log4j-slf4j-impl"));
commonExclusions.add(MavenDependencies.createExclusion("log4j", "apache-log4j-extras"));
commonExclusions.add(MavenDependencies.createExclusion("org.slf4j", "slf4j-simple"));
commonExclusions.add(MavenDependencies.createExclusion("org.slf4j", "slf4j-jdk14"));
commonExclusions.add(MavenDependencies.createExclusion("ch.qos.logback", "logback-classic"));
commonExclusions.add(MavenDependencies.createExclusion("ch.qos.logback", "logback-core"));
for (String ex : config.getMavenExclusions()) {
commonExclusions.add(MavenDependencies.createExclusion(ex));
}
// Module dependencies
List<MavenDependency> additionalDependencies = new LinkedList<>();
for (String canonicalForm : config.getAdditionalDependencies()) {
MavenCoordinate coord = MavenCoordinates.createCoordinate(canonicalForm);
MavenDependency dep = MavenDependencies.createDependency(coord, ScopeType.RUNTIME, false);
additionalDependencies.add(dep);
}
// String mainArtifactId = config.getModuleName() + "-starter";
// MavenCoordinate mainJar = MavenCoordinates.createCoordinate(config.getMavenGroup(), mainArtifactId, version, PackagingType.JAR, null);
// // Add exclusions only when not using the starters
// MavenDependency mainDep = MavenDependencies.createDependency(mainJar, ScopeType.COMPILE, false);
// moduleDependencies.add(mainDep);
List<String> testProvidedDependenciesXml = new LinkedList<>();
List<ScopeType> scopes = new LinkedList<>();
if (config.getIncludeProvidedDependencies() || config.getIncludeTestDependencies() || config.getUnitTestEnabled()) {
if (config.getIncludeTestDependencies() || config.getUnitTestEnabled()) {
testProvidedDependenciesXml.addAll(DependencyResolver.getDependencies(config.getModuleBasePath() + "/pom.xml", ScopeType.TEST.toString()));
scopes.add(ScopeType.TEST);
}
if (config.getIncludeProvidedDependencies()) {
testProvidedDependenciesXml.addAll(DependencyResolver.getDependencies(config.getModuleBasePath() + "/pom.xml", ScopeType.PROVIDED.toString()));
scopes.add(ScopeType.PROVIDED);
}
}
List<String> cleanTestProvidedDependenciesXml = new LinkedList<>();
for (String depXml : testProvidedDependenciesXml) {
if (validTestDependency(config, depXml, commonExclusions)) {
depXml = useBOMVersionIfPresent(config, depXml);
depXml = enforceExclusions(config, depXml, commonExclusions);
depXml = switchToStarterIfPresent(config, depXml);
cleanTestProvidedDependenciesXml.add(depXml);
}
}
// List<MavenResolvedArtifact> testDependencies = new LinkedList<>();
// if (!cleanTestProvidedDependenciesXml.isEmpty()) {
//
// File testProvidedResolverPom = createResolverPom(config, cleanTestProvidedDependenciesXml);
//
// testDependencies.addAll(Arrays.asList(resolver(config)
// .loadPomFromFile(testProvidedResolverPom)
// .importDependencies(scopes.toArray(new ScopeType[0]))
// .resolve()
// .withTransitivity()
// .asResolvedArtifact()));
// }
File moduleSpringBootPom = createUserPom(config, cleanTestProvidedDependenciesXml);
List<ScopeType> resolvedScopes = new LinkedList<>();
resolvedScopes.add(ScopeType.COMPILE);
resolvedScopes.add(ScopeType.RUNTIME);
resolvedScopes.addAll(scopes);
List<MavenResolvedArtifact> runtimeDependencies = new LinkedList<>();
try {
runtimeDependencies.addAll(Arrays.asList(resolver(config)
.loadPomFromFile(moduleSpringBootPom)
.importDependencies(resolvedScopes.toArray(new ScopeType[0]))
.addDependencies(additionalDependencies)
.resolve()
.withTransitivity()
.asResolvedArtifact()));
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage(), e);
}
List<MavenResolvedArtifact> dependencyArtifacts = runtimeDependencies; //merge(config, runtimeDependencies, testDependencies);
lookForVersionMismatch(config, dependencyArtifacts);
List<File> dependencies = new LinkedList<>();
for (MavenResolvedArtifact a : dependencyArtifacts) {
dependencies.add(a.asFile());
}
// The spring boot-loader dependency will be added to the main jar, so it should be excluded from the embedded ones
excludeDependencyRegex(dependencies, "^spring-boot-loader-[0-9].*");
// Add all dependencies as spring-boot nested jars
ark = addDependencies(ark, dependencies);
// Add common packages to main jar
ark = ark.addPackages(true, "org.jboss.shrinkwrap");
// Add current classes to both location to be used by different classloaders
ark = ark.addPackages(true, "org.apache.camel.itest.springboot");
ark = addSpringbootPackage(ark, "org.apache.camel.itest.springboot");
// CAMEL-10060 is resolved since 2.18 but some unit tests use custom (non spring-boot enabled) camel contexts
ark = ark.addPackages(true, "org.apache.camel.converter.myconverter");
ark = ark.addPackages(true, "org.springframework.boot.loader");
ClassPath.Builder external = ClassPath.builder().add(ark);
// overcome limitations of some JDKs
external.addSystemProperty("javax.xml.accessExternalDTD", "all");
external.addSystemProperty("javax.xml.accessExternalSchema", "all");
if (config.getUnitTestEnabled()) {
external.addSystemProperty("container.user.dir", new File(config.getModuleBasePath()).getCanonicalPath());
external.addSystemProperty("container.test.resources.dir", new File(config.getModuleBasePath()).getCanonicalPath() + "/target/test-classes");
}
// Adding configuration properties
for (Map.Entry<Object, Object> e : System.getProperties().entrySet()) {
if (e.getKey() instanceof String && e.getValue() instanceof String) {
String key = (String) e.getKey();
if (key.startsWith(ITestConfigBuilder.CONFIG_PREFIX)) {
external.addSystemProperty(key, (String) e.getValue());
}
}
}
for (Map.Entry<String, String> e : config.getSystemProperties().entrySet()) {
external.addSystemProperty(e.getKey(), e.getValue());
}
return external.build();
}
private static void lookForVersionMismatch(ITestConfig config, List<MavenResolvedArtifact> dependencyArtifacts) {
Set<String> ignore = new HashSet<>();
ignore.addAll(config.getIgnoreLibraryMismatch());
// A list of known libraries that don't follow the all-artifacts-same-version convention
ignore.add("com.atlassian.jira:jira-rest-java-client-api");
ignore.add("com.fasterxml.jackson.module:jackson-module-scala_2.11"); // latest version not available
ignore.add("com.github.jnr");
ignore.add("com.sun.xml.bind:jaxb-xjc");
ignore.add("com.azure:azure");
ignore.add("com.datastax.oss:java");
ignore.add("com.jcabi:jcabi");
ignore.add("commons-beanutils:commons-beanutils");
ignore.add("io.dropwizard.metrics:metrics-json"); // PR to spring-boot
ignore.add("io.dropwizard.metrics:metrics-jvm"); // PR to spring-boot
ignore.add("io.fabric8:kubernetes-");
ignore.add("io.netty:netty:jar"); // an old version
ignore.add("io.netty:netty-tcnative-boringssl-static");
ignore.add("io.swagger:swagger-parser");
ignore.add("io.opencensus:opencensus-");
ignore.add("io.opentracing.contrib:opentracing-");
ignore.add("org.apache.commons");
ignore.add("org.apache.curator");
ignore.add("org.apache.cxf:cxf-api");
ignore.add("org.apache.geronimo.specs");
ignore.add("org.apache.flink:flink-shaded-asm");
ignore.add("org.apache.flink:flink-shaded-guava");
ignore.add("org.apache.flink:flink-shaded-jackson");
ignore.add("org.apache.flink:flink-shaded-netty");
ignore.add("org.apache.logging.log4j:log4j-jcl");
ignore.add("org.apache.maven");
ignore.add("org.apache.parquet");
ignore.add("org.apache.solr:solr-solrj"); // PR to spring-boot
ignore.add("org.apache.velocity");
ignore.add("org.apache.qpid:qpid-jms-client");
ignore.add("org.opensaml");
ignore.add("org.ow2.asm"); // No problem
ignore.add("org.codehaus.plexus");
ignore.add("org.eclipse.jetty.websocket:websocket-api"); // PR to spring-boot
ignore.add("org.jboss.arquillian.container");
ignore.add("org.jboss:");
ignore.add("org.hibernate:hibernate-validator"); // does not match with hibernate-core
ignore.add("org.mortbay.jetty:servlet-api-2.5");
ignore.add("org.scala-lang:scala-compiler");
ignore.add("org.slf4j:slf4j-ext"); // PR to spring-boot
ignore.add("org.easytesting");
ignore.add("net.java.dev.jna:jna-platform"); // PR to spring-boot
ignore.add("net.openhft");
ignore.add("org.scala-lang.modules:scala-java8-compat_2.11");
ignore.add("org.scala-lang.modules:scala-parser-combinators_2.12");
ignore.add("org.scala-lang.modules:scala-xml_2.12");
ignore.add("net.sourceforge.htmlunit:htmlunit-core-js"); // v 2.21 does not exist
ignore.add("org.springframework.cloud"); // too many different versions
ignore.add("org.springframework.data");
ignore.add("org.springframework.security:spring-security-jwt");
ignore.add("org.springframework.security:spring-security-rsa");
ignore.add("org.springframework.social");
ignore.add("org.webjars"); // No problem
ignore.add("stax:stax-api");
ignore.add("xml-apis:xml-apis-ext");
ignore.add("org.jboss.logging");
ignore.add("org.jboss.marshalling");
ignore.add("org.jgroups:jgroups-raft");
ignore.add("net.sourceforge.htmlunit:htmlunit");
ignore.add("ai.djl.mxnet:mxnet-engine");
ignore.add("ai.djl.mxnet:mxnet-model-zoo");
ignore.add("ai.djl.mxnet:mxnet-native-auto");
ignore.add("org.sonatype.plexus");
ignore.add("org.sonatype.sisu");
ignore.add("com.healthmarketscience.jackcess");
ignore.add("com.google.cloud");
ignore.add("com.google.api");
ignore.add("com.google.http-client");
ignore.add("org.eclipse.rdf4j");
// these are from camel-spring-boot and not camel repo so ignore them
ignore.add("org.apache.camel:camel-spring-cloud-consul");
ignore.add("org.apache.camel:camel-spring-cloud-netflix");
ignore.add("org.apache.camel:camel-spring-cloud");
ignore.add("org.apache.camel:camel-spring-boot");
// google grpc is a mix of all sort of different versions
ignore.add("com.google.api.grpc");
// microsoft azure msal4j-persistence-extension library introduced by datalake component
ignore.add("com.microsoft.azure:msal4j-persistence-extension");
Map<String, Map<String, String>> status = new TreeMap<>();
Set<String> mismatches = new TreeSet<>();
for (MavenResolvedArtifact a : dependencyArtifacts) {
boolean ignoreCheck = false;
for (String i : ignore) {
if (getIdentifier(a).startsWith(i)) {
ignoreCheck = true;
break;
}
}
if (ignoreCheck) {
continue;
}
String group = a.getCoordinate().getGroupId();
String artifact = a.getCoordinate().getArtifactId();
String version = a.getCoordinate().getVersion();
String artifactPrefix = artifact;
if (artifactPrefix.contains("-")) {
artifactPrefix = artifactPrefix.substring(0, artifactPrefix.indexOf("-"));
}
String prefixId = group + ":" + artifactPrefix;
if (!status.containsKey(prefixId)) {
status.put(prefixId, new TreeMap<>());
}
for (String anotherVersion : status.get(prefixId).values()) {
if (!sameVersion(anotherVersion, version)) {
mismatches.add(prefixId);
}
}
status.get(prefixId).put(getIdentifier(a), version);
}
StringBuilder message = new StringBuilder();
for (String mismatch : mismatches) {
message.append("Found mismatch for dependency " + mismatch + ":\n");
for (String art : status.get(mismatch).keySet()) {
String ver = status.get(mismatch).get(art);
message.append(" - " + art + " --> " + ver + "\n");
}
}
if (message.length() > 0) {
String alert = "Library version mismatch found.\n" + message;
if (FAIL_ON_RELATED_LIBRARY_MISMATCH) {
throw new InvocationException(new RuntimeException(alert));
} else {
debug(alert);
}
}
}
private static boolean sameVersion(String v1, String v2) {
if (VERSION_EQUALITY_MINOR_VERSION) {
if (v1.indexOf(".") != v1.lastIndexOf(".") && v2.indexOf(".") != v2.lastIndexOf(".")) {
// truncate up to minor version
int v1MinSplit = v1.indexOf(".", v1.indexOf(".") + 1);
v1 = v1.substring(0, v1MinSplit);
int v2MinSplit = v2.indexOf(".", v2.indexOf(".") + 1);
v2 = v2.substring(0, v2MinSplit);
}
}
return v1.equals(v2);
}
private static String getIdentifier(MavenResolvedArtifact a) {
return a.getCoordinate().getGroupId() + ":" + a.getCoordinate().getArtifactId() + ":" + a.getCoordinate().getType() + ":" + a.getCoordinate().getClassifier();
}
private static File createUserPom(ITestConfig config, List<String> cleanTestProvidedDependencies) throws Exception {
String pom;
String template = "/application-pom-sb" + config.getSpringBootMajorVersion() + ".xml";
try (InputStream pomTemplate = ArquillianPackager.class.getResourceAsStream(template)) {
pom = IOUtils.toString(pomTemplate);
}
StringBuilder dependencies = new StringBuilder();
for (String dep : cleanTestProvidedDependencies) {
dependencies.append(dep);
dependencies.append("\n");
}
pom = pom.replace("<!-- DEPENDENCIES -->", dependencies.toString());
Map<String, String> resolvedProperties = new TreeMap<>();
Matcher m = PROP_PATTERN.matcher(pom);
while (m.find()) {
String property = m.group();
String resolved = DependencyResolver.resolveModuleOrParentProperty(new File(new File(config.getModuleBasePath()), "pom.xml"), property);
resolvedProperties.put(property, resolved);
}
for (String property : resolvedProperties.keySet()) {
pom = pom.replace(property, resolvedProperties.get(property));
}
pom = pom.replace("#{module}", config.getModuleName());
// some modules are not in component-starter
String path = config.getModuleBasePath();
if (path.contains("camel-spring-cloud-netflix")) {
path = "../camel-spring-cloud-netflix";
} else if (path.contains("camel-spring-cloud-consul")) {
path = "../camel-spring-cloud-consul";
} else if (path.contains("camel-spring-cloud")) {
path = "../camel-spring-cloud";
}
File pomFile = new File(path + "/target/itest-spring-boot-pom.xml");
pomFile.getParentFile().mkdirs();
try (FileWriter fw = new FileWriter(pomFile)) {
IOUtils.write(pom, fw);
}
return pomFile;
}
private static ConfigurableMavenResolverSystem resolver(ITestConfig config) {
return Maven.configureResolver().workOffline(config.getMavenOfflineResolution());
}
private static ClassLoader getExtensionClassloader() {
ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
@Override
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
return cl;
}
private static boolean validTestDependency(ITestConfig config, String dependencyXml, List<MavenDependencyExclusion> exclusions) {
boolean valid = true;
for (MavenDependencyExclusion excl : exclusions) {
String groupId = excl.getGroupId();
String artifactId = excl.getArtifactId();
boolean notExclusion = dependencyXml.indexOf("<exclusions>") < 0 || dependencyXml.indexOf(groupId) < dependencyXml.indexOf("<exclusions>");
if (dependencyXml.contains(groupId) && dependencyXml.contains(artifactId) && notExclusion) {
valid = false;
break;
}
}
if (!valid) {
debug("Discarded test dependency: " + dependencyXml.replace("\n", "").replace("\r", "").replace("\t", ""));
}
return valid;
}
private static String enforceExclusions(ITestConfig config, String dependencyXml, List<MavenDependencyExclusion> exclusions) {
if (!dependencyXml.contains("<exclusions>")) {
dependencyXml = dependencyXml.replace("</dependency>", "<exclusions></exclusions></dependency>");
}
for (MavenDependencyExclusion excl : exclusions) {
String groupId = excl.getGroupId();
String artifactId = excl.getArtifactId();
dependencyXml = dependencyXml.replace("</exclusions>", "<exclusion><groupId>" + groupId + "</groupId><artifactId>" + artifactId + "</artifactId></exclusion></exclusions>");
}
return dependencyXml;
}
private static String switchToStarterIfPresent(ITestConfig config, String dependencyXml) {
String groupId = textBetween(dependencyXml, "<groupId>", "</groupId>");
String artifactId = textBetween(dependencyXml, "<artifactId>", "</artifactId>");
String type = textBetween(dependencyXml, "<type>", "</type>");
if ("org.apache.camel".equals(groupId) && artifactId.startsWith("camel-") && !"test-jar".equals(type)) {
String starterArtifact = artifactId + "-starter";
File starterFile = new File("../../components-starter/" + starterArtifact);
if (starterFile.exists()) {
dependencyXml = dependencyXml.replace(artifactId, starterArtifact);
}
}
return dependencyXml;
}
private static String useBOMVersionIfPresent(ITestConfig config, String dependencyXml) {
String groupId = textBetween(dependencyXml, "<groupId>", "</groupId>");
String artifactId = textBetween(dependencyXml, "<artifactId>", "</artifactId>");
String version = config.getTestLibraryVersions().get(groupId + ":" + artifactId);
boolean stripVersion = false;
if (version == null) {
boolean testsLib = dependencyXml.contains("<classifier>tests");
stripVersion = !testsLib && BOMResolver.getInstance(config).getBOMVersion(groupId, artifactId) != null;
// skip if its org.infinispan as we need explict version to work-around a problem when using test-jar dependencies
if ("org.infinispan".equals(groupId)) {
stripVersion = false;
}
}
if (version != null) {
if (dependencyXml.contains("<version>")) {
int from = dependencyXml.indexOf("<version>") + 9;
int to = dependencyXml.indexOf("</version>");
dependencyXml = dependencyXml.substring(0, from) + version + dependencyXml.substring(to);
} else {
String kw = "</artifactId>";
int pos = dependencyXml.indexOf(kw) + kw.length();
dependencyXml = dependencyXml.substring(0, pos) + "<version>" + version + "</version>" + dependencyXml.substring(pos);
}
} else if (stripVersion && dependencyXml.contains("<version>")) {
int from = dependencyXml.indexOf("<version>");
int to = dependencyXml.indexOf("</version>") + 10;
dependencyXml = dependencyXml.substring(0, from) + dependencyXml.substring(to);
}
return dependencyXml;
}
private static String textBetween(String text, String start, String end) {
int sp = text.indexOf(start);
int rsp = sp + start.length();
int ep = text.indexOf(end);
if (sp < 0 || ep < 0 || ep <= rsp) {
return null;
}
String res = text.substring(rsp, ep);
return res;
}
private static boolean excludeDependencyRegex(List<File> dependencies, String regex) {
Pattern pattern = Pattern.compile(regex);
int count = 0;
for (Iterator<File> it = dependencies.iterator(); it.hasNext();) {
File f = it.next();
if (pattern.matcher(f.getName()).matches()) {
it.remove();
count++;
break;
}
}
return count > 0;
}
private static JavaArchive addDependencies(JavaArchive ark, Collection<File> deps) {
Set<File> dependencySet = new HashSet<>(deps);
for (File d : dependencySet) {
debug("Adding spring-boot dependency: " + d.getName());
ark = ark.add(new FileAsset(d), LIB_FOLDER + "/" + d.getName());
}
return ark;
}
private static JavaArchive addSpringbootPackage(JavaArchive ark, String... packageNames) throws Exception {
Iterable<ClassLoader> classLoaders = Collections.singleton(Thread.currentThread().getContextClassLoader());
for (String packageName : packageNames) {
for (final ClassLoader classLoader : classLoaders) {
final URLPackageScanner.Callback callback = new URLPackageScanner.Callback() {
@Override
public void classFound(String className, Asset asset) {
ArchivePath classNamePath = AssetUtil.getFullPathForClassResource(className);
asset = new ClassLoaderAsset(classNamePath.get().substring(1), classLoader);
ArchivePath location = new BasicPath(CLASSES_FOLDER + "/", classNamePath);
ark.add(asset, location);
}
};
final URLPackageScanner scanner = URLPackageScanner.newInstance(true, classLoader, callback, packageName);
scanner.scanPackage();
}
}
return ark;
}
private static void debug(String str) {
if (DEBUG_ENABLED) {
System.out.println("DEBUG>>> " + str);
}
}
}