diff --git a/tests/integration-tests-utils/pom.xml b/tests/integration-tests-utils/pom.xml
index 3593ec50746..ca3608a6315 100644
--- a/tests/integration-tests-utils/pom.xml
+++ b/tests/integration-tests-utils/pom.xml
@@ -34,6 +34,7 @@
Apache BookKeeper :: Tests :: Utility module for Arquillian based integration tests
+ 3.0.1
1.13.0
1.15
@@ -45,6 +46,17 @@
${commons-compress.version}
+
+ org.jboss.shrinkwrap.resolver
+ shrinkwrap-resolver-impl-maven
+ ${shrinkwrap.version}
+
+
+ org.jboss.shrinkwrap.resolver
+ shrinkwrap-resolver-api
+ ${shrinkwrap.version}
+
+
org.apache.zookeeper
zookeeper
@@ -81,4 +93,20 @@
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ 0
+
+
+
+
+
diff --git a/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java
new file mode 100644
index 00000000000..6f31f5c7665
--- /dev/null
+++ b/tests/integration-tests-utils/src/main/java/org/apache/bookkeeper/tests/MavenClassLoader.java
@@ -0,0 +1,117 @@
+/**
+ *
+ * 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.bookkeeper.tests;
+
+import com.google.common.collect.Lists;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+import org.jboss.shrinkwrap.resolver.api.maven.Maven;
+import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependencies;
+import org.jboss.shrinkwrap.resolver.api.maven.coordinate.MavenDependency;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MavenClassLoader implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(MavenClassLoader.class);
+
+ private MavenClassLoader(URLClassLoader cl) {
+ this.classloader = cl;
+ }
+
+ private final URLClassLoader classloader;
+
+ public static MavenClassLoader forArtifact(String mainArtifact) throws Exception {
+ Optional slf4jVersion = Arrays.stream(Maven.resolver().resolve(mainArtifact)
+ .withTransitivity().asResolvedArtifact())
+ .filter((a) -> a.getCoordinate().getGroupId().equals("org.slf4j")
+ && a.getCoordinate().getArtifactId().equals("slf4j-log4j12"))
+ .map((a) -> a.getCoordinate().getVersion())
+ .findFirst();
+
+ List deps = Lists.newArrayList(
+ MavenDependencies.createDependency(
+ mainArtifact, ScopeType.COMPILE, false,
+ MavenDependencies.createExclusion("org.slf4j:slf4j-log4j12"),
+ MavenDependencies.createExclusion("log4j:log4j")));
+ if (slf4jVersion.isPresent()) {
+ deps.add(MavenDependencies.createDependency("org.slf4j:slf4j-simple:" + slf4jVersion.get(),
+ ScopeType.COMPILE, false));
+ }
+
+ File[] files = Maven.resolver().addDependencies(deps.toArray(new MavenDependency[0]))
+ .resolve().withTransitivity().asFile();
+ URLClassLoader cl = AccessController.doPrivileged(
+ new PrivilegedAction() {
+ @Override
+ public URLClassLoader run() {
+ return new URLClassLoader(Arrays.stream(files)
+ .map((f) -> {
+ try {
+ return f.toURI().toURL();
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ })
+ .toArray(URL[]::new),
+ ClassLoader.getSystemClassLoader());
+ }
+ });
+ return new MavenClassLoader(cl);
+ }
+
+ public static MavenClassLoader forBookKeeperVersion(String version) throws Exception {
+ return forArtifact("org.apache.bookkeeper:bookkeeper-server:" + version);
+ }
+
+ public Object newInstance(String className, Object... args) throws Exception {
+ Class> klass = Class.forName(className, true, classloader);
+ return klass.getConstructor(Arrays.stream(args).map((a)-> a.getClass()).toArray(Class[]::new))
+ .newInstance(args);
+ }
+
+ public Object newBookKeeper(String zookeeper) throws Exception {
+ return newInstance("org.apache.bookkeeper.client.BookKeeper", zookeeper);
+ }
+
+ public Object digestType(String type) throws Exception {
+ String className = "org.apache.bookkeeper.client.BookKeeper$DigestType";
+ for (Object o : classloader.loadClass(className).getEnumConstants()) {
+ if (o.toString().equals(type)) {
+ return o;
+ }
+ }
+ throw new ClassNotFoundException("No such digest type " + type);
+ }
+
+ public void close() throws Exception {
+ classloader.close();
+ }
+}
diff --git a/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java b/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java
new file mode 100644
index 00000000000..930355787e2
--- /dev/null
+++ b/tests/integration-tests-utils/src/test/java/org/apache/bookkeeper/tests/MavenClassLoaderTest.java
@@ -0,0 +1,42 @@
+/**
+ *
+ * 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.bookkeeper.tests;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MavenClassLoaderTest {
+ @Test(expected=ClassNotFoundException.class)
+ public void testLog4JReplacement() throws Exception {
+ MavenClassLoader.forBookKeeperVersion("4.0.0")
+ .newInstance("org.apache.log4j.Logger");
+ }
+
+ @Test
+ public void testNoZooKeeperInterference() throws Exception {
+ // Use KeeperException, because ZooKeeper needs a watcher which would be a pain to construct
+ Object o = MavenClassLoader.forBookKeeperVersion("4.0.0")
+ .newInstance("org.apache.zookeeper.KeeperException$NoNodeException");
+ Assert.assertFalse(o.getClass().equals(
+ org.apache.zookeeper.KeeperException.NoNodeException.class));
+ }
+
+}