/*
* 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);
}
}