/* * Copyright (c) 2011-2015 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package io.vertx.core; import io.vertx.test.spi.FakeFactory; import io.vertx.test.spi.NotImplementedSPI; import io.vertx.test.spi.SomeFactory; import org.junit.Before; import org.junit.Test; import javax.tools.*; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; /** * Check the service helper behavior. * * @author <a href="http://escoffier.me">Clement Escoffier</a> */ public class ServiceHelperTest { @Before public void setUp() throws IOException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); File output = new File("target/externals"); output.mkdirs(); fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singletonList( output)); List<File> classesToCompile = new ArrayList<>(); classesToCompile.add(new File("src/test/externals/MyVerticle.java")); classesToCompile.add(new File("src/test/externals/SomeFactoryImplA.java")); Iterable<? extends JavaFileObject> compilationUnits1 = fileManager.getJavaFileObjectsFromFiles(classesToCompile); compiler.getTask(null, fileManager, null, null, null, compilationUnits1).call(); // Also copy the META-INF dir File source = new File("src/test/externals/META-INF/services/io.vertx.test.spi.SomeFactory"); File out = new File("target/externals/META-INF/services/io.vertx.test.spi.SomeFactory"); out.getParentFile().mkdirs(); Files.copy(source.toPath(), out.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); } @Test public void loadFactory() throws Exception { FakeFactory factory = ServiceHelper.loadFactory(FakeFactory.class); assertThat(factory.classloader()).isEqualTo(ServiceHelperTest.class.getClassLoader()); } @Test(expected = IllegalStateException.class) public void loadNotImplementedSPI() throws Exception { ServiceHelper.loadFactory(NotImplementedSPI.class); } @Test public void loadFactoryOrNull() throws Exception { NotImplementedSPI factory = ServiceHelper.loadFactoryOrNull(NotImplementedSPI.class); assertThat(factory).isNull(); FakeFactory fake = ServiceHelper.loadFactoryOrNull(FakeFactory.class); assertThat(fake).isNotNull(); assertThat(fake.classloader()).isEqualTo(ServiceHelperTest.class.getClassLoader()); } @Test public void loadFactories() throws Exception { Collection<FakeFactory> factories = ServiceHelper.loadFactories(FakeFactory.class); assertThat(factories) .isNotNull() .hasSize(2); Collection<NotImplementedSPI> impl = ServiceHelper.loadFactories(NotImplementedSPI.class); assertThat(impl) .isNotNull() .hasSize(0); } @Test public void loadFactoriesWithClassloader() throws Exception { ClassLoader custom = new URLClassLoader(new URL[]{new File("target/externals").toURI().toURL()}); // Try without the custom classloader. Collection<SomeFactory> factories = ServiceHelper.loadFactories(SomeFactory.class); assertThat(factories) .isNotNull() .hasSize(0); // Try with the custom classloader factories = ServiceHelper.loadFactories(SomeFactory.class, custom); assertThat(factories) .isNotNull() .hasSize(1); assertThat(factories.iterator().next().classloader()).isEqualTo(custom); } @Test public void loadFactoriesFromTCCL() throws Exception { ClassLoader custom = new URLClassLoader(new URL[]{new File("target/externals").toURI().toURL()}); // Try without the TCCL classloader. Collection<SomeFactory> factories = ServiceHelper.loadFactories(SomeFactory.class); assertThat(factories) .isNotNull() .hasSize(0); // Try with the TCCL classloader final ClassLoader originalTCCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(custom); factories = ServiceHelper.loadFactories(SomeFactory.class); assertThat(factories) .isNotNull() .hasSize(1); assertThat(factories.iterator().next().classloader()).isEqualTo(custom); } finally { Thread.currentThread().setContextClassLoader(originalTCCL); } } @Test public void loadFactoriesWithVertxClassloader() throws Exception { // This test is a bit more tricky as we need to load the ServiceHelper class from a custom classloader. ClassLoader custom = new URLClassLoader(new URL[]{ new File("target/classes").toURI().toURL(), new File("target/test-classes").toURI().toURL(), new File("target/externals").toURI().toURL(), }, null); Class serviceHelperClass = custom.loadClass(ServiceHelper.class.getName()); Class someFactoryClass = custom.loadClass(SomeFactory.class.getName()); assertThat(serviceHelperClass.getClassLoader()).isEqualTo(custom); assertThat(someFactoryClass.getClassLoader()).isEqualTo(custom); Method method = serviceHelperClass.getMethod("loadFactories", Class.class); Collection collection = (Collection) method.invoke(null, someFactoryClass); assertThat(collection).hasSize(1); } }