*/ | */ | ||||
package org.pf4j; | package org.pf4j; | ||||
import com.google.common.collect.ImmutableList; | |||||
import com.google.common.io.ByteStreams; | |||||
import com.google.testing.compile.Compilation; | |||||
import java.util.Comparator; | |||||
import java.util.UUID; | |||||
import org.junit.jupiter.api.AfterEach; | import org.junit.jupiter.api.AfterEach; | ||||
import org.junit.jupiter.api.Assertions; | |||||
import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||
import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||
import org.pf4j.test.FailTestPlugin; | |||||
import org.pf4j.test.JavaFileObjectClassLoader; | |||||
import org.pf4j.test.JavaFileObjectUtils; | |||||
import org.pf4j.test.JavaSources; | |||||
import org.pf4j.test.TestExtension; | |||||
import org.pf4j.test.TestExtensionPoint; | import org.pf4j.test.TestExtensionPoint; | ||||
import javax.tools.JavaFileObject; | import javax.tools.JavaFileObject; | ||||
import java.io.IOException; | |||||
import java.util.ArrayList; | |||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.HashMap; | |||||
import java.util.HashSet; | import java.util.HashSet; | ||||
import java.util.LinkedHashMap; | import java.util.LinkedHashMap; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Map; | import java.util.Map; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.UUID; | |||||
import static com.google.testing.compile.CompilationSubject.assertThat; | |||||
import static com.google.testing.compile.Compiler.javac; | |||||
import static org.junit.Assert.assertNull; | |||||
import static org.junit.jupiter.api.Assertions.assertEquals; | import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
import static org.junit.jupiter.api.Assertions.assertNotNull; | |||||
import static org.mockito.Mockito.eq; | |||||
import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||
import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||
when(pluginStopped.getPluginState()).thenReturn(PluginState.STOPPED); | when(pluginStopped.getPluginState()).thenReturn(PluginState.STOPPED); | ||||
pluginManager = mock(PluginManager.class); | pluginManager = mock(PluginManager.class); | ||||
when(pluginManager.getPlugin(eq("plugin1"))).thenReturn(pluginStarted); | |||||
when(pluginManager.getPlugin(eq("plugin2"))).thenReturn(pluginStopped); | |||||
when(pluginManager.getPluginClassLoader(eq("plugin1"))).thenReturn(getClass().getClassLoader()); | |||||
when(pluginManager.getPlugin("plugin1")).thenReturn(pluginStarted); | |||||
when(pluginManager.getPlugin("plugin2")).thenReturn(pluginStopped); | |||||
when(pluginManager.getPluginClassLoader("plugin1")).thenReturn(getClass().getClassLoader()); | |||||
when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory()); | when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory()); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
List<ExtensionWrapper<FailTestPlugin>> list = instance.find(FailTestPlugin.class); | |||||
List<ExtensionWrapper<TestExtension>> list = instance.find(TestExtension.class); | |||||
assertEquals(0, list.size()); | assertEquals(0, list.size()); | ||||
} | } | ||||
Set<String> bucket = new HashSet<>(); | Set<String> bucket = new HashSet<>(); | ||||
bucket.add("org.pf4j.test.TestExtension"); | bucket.add("org.pf4j.test.TestExtension"); | ||||
bucket.add("org.pf4j.test.FailTestExtension"); | |||||
entries.put(null, bucket); | entries.put(null, bucket); | ||||
return entries; | return entries; | ||||
}; | }; | ||||
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class); | List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class); | ||||
assertEquals(2, list.size()); | |||||
assertEquals(1, list.size()); | |||||
} | } | ||||
/** | /** | ||||
Set<String> bucket = new HashSet<>(); | Set<String> bucket = new HashSet<>(); | ||||
bucket.add("org.pf4j.test.TestExtension"); | bucket.add("org.pf4j.test.TestExtension"); | ||||
bucket.add("org.pf4j.test.FailTestExtension"); | |||||
entries.put("plugin1", bucket); | entries.put("plugin1", bucket); | ||||
bucket = new HashSet<>(); | bucket = new HashSet<>(); | ||||
bucket.add("org.pf4j.test.TestExtension"); | bucket.add("org.pf4j.test.TestExtension"); | ||||
}; | }; | ||||
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class); | List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class); | ||||
assertEquals(2, list.size()); | |||||
assertEquals(1, list.size()); | |||||
list = instance.find(TestExtensionPoint.class, "plugin1"); | list = instance.find(TestExtensionPoint.class, "plugin1"); | ||||
assertEquals(2, list.size()); | |||||
assertEquals(1, list.size()); | |||||
list = instance.find(TestExtensionPoint.class, "plugin2"); | list = instance.find(TestExtensionPoint.class, "plugin2"); | ||||
// "0" because the status of "plugin2" is STOPPED => no extensions | |||||
assertEquals(0, list.size()); | assertEquals(0, list.size()); | ||||
} | } | ||||
*/ | */ | ||||
@Test | @Test | ||||
public void testFindExtensionWrappersFromPluginId() { | public void testFindExtensionWrappersFromPluginId() { | ||||
// complicate the test to show hot to deal with dynamic Java classes (generated at runtime from sources) | |||||
PluginWrapper plugin3 = mock(PluginWrapper.class); | |||||
JavaFileObject object = JavaSources.compile(DefaultExtensionFactoryTest.FailTestExtension); | |||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
classLoader.load(object); | |||||
when(plugin3.getPluginClassLoader()).thenReturn(classLoader); | |||||
when(plugin3.getPluginState()).thenReturn(PluginState.STARTED); | |||||
when(pluginManager.getPluginClassLoader("plugin3")).thenReturn(classLoader); | |||||
when(pluginManager.getPlugin("plugin3")).thenReturn(plugin3); | |||||
ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) { | ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) { | ||||
@Override | @Override | ||||
Set<String> bucket = new HashSet<>(); | Set<String> bucket = new HashSet<>(); | ||||
bucket.add("org.pf4j.test.TestExtension"); | bucket.add("org.pf4j.test.TestExtension"); | ||||
bucket.add("org.pf4j.test.FailTestExtension"); | |||||
entries.put("plugin1", bucket); | entries.put("plugin1", bucket); | ||||
bucket = new HashSet<>(); | bucket = new HashSet<>(); | ||||
bucket.add("org.pf4j.test.TestExtension"); | bucket.add("org.pf4j.test.TestExtension"); | ||||
entries.put("plugin2", bucket); | entries.put("plugin2", bucket); | ||||
bucket = new HashSet<>(); | |||||
bucket.add(JavaFileObjectUtils.getClassName(object)); | |||||
entries.put("plugin3", bucket); | |||||
return entries; | return entries; | ||||
} | } | ||||
}; | }; | ||||
List<ExtensionWrapper> plugin1Result = instance.find("plugin1"); | List<ExtensionWrapper> plugin1Result = instance.find("plugin1"); | ||||
assertEquals(2, plugin1Result.size()); | |||||
assertEquals(1, plugin1Result.size()); | |||||
List<ExtensionWrapper> plugin2Result = instance.find("plugin2"); | List<ExtensionWrapper> plugin2Result = instance.find("plugin2"); | ||||
assertEquals(0, plugin2Result.size()); | assertEquals(0, plugin2Result.size()); | ||||
List<ExtensionWrapper> plugin3Result = instance.find(UUID.randomUUID().toString()); | |||||
assertEquals(0, plugin3Result.size()); | |||||
List<ExtensionWrapper> plugin3Result = instance.find("plugin3"); | |||||
assertEquals(1, plugin3Result.size()); | |||||
List<ExtensionWrapper> plugin4Result = instance.find(UUID.randomUUID().toString()); | |||||
assertEquals(0, plugin4Result.size()); | |||||
} | } | ||||
@Test | @Test | ||||
public void findExtensionAnnotation() throws Exception { | |||||
Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting, | |||||
ExtensionAnnotationProcessorTest.WhazzupGreeting); | |||||
assertThat(compilation).succeededWithoutWarnings(); | |||||
ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles(); | |||||
public void findExtensionAnnotation() { | |||||
List<JavaFileObject> generatedFiles = JavaSources.compileAll(JavaSources.Greeting, JavaSources.WhazzupGreeting); | |||||
assertEquals(2, generatedFiles.size()); | assertEquals(2, generatedFiles.size()); | ||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
Map<String, Class<?>> loadedClasses = classLoader.loadClasses(new ArrayList<>(generatedFiles)); | |||||
Map<String, Class<?>> loadedClasses = new JavaFileObjectClassLoader().load(generatedFiles); | |||||
Class<?> clazz = loadedClasses.get("test.WhazzupGreeting"); | Class<?> clazz = loadedClasses.get("test.WhazzupGreeting"); | ||||
Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz); | Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz); | ||||
assertNotNull(extension); | |||||
Assertions.assertNotNull(extension); | |||||
} | } | ||||
@Test | @Test | ||||
public void findExtensionAnnotationThatMissing() throws Exception { | |||||
Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting, | |||||
public void findExtensionAnnotationThatMissing() { | |||||
List<JavaFileObject> generatedFiles = JavaSources.compileAll(JavaSources.Greeting, | |||||
ExtensionAnnotationProcessorTest.SpinnakerExtension_NoExtension, | ExtensionAnnotationProcessorTest.SpinnakerExtension_NoExtension, | ||||
ExtensionAnnotationProcessorTest.WhazzupGreeting_SpinnakerExtension); | ExtensionAnnotationProcessorTest.WhazzupGreeting_SpinnakerExtension); | ||||
assertThat(compilation).succeededWithoutWarnings(); | |||||
ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles(); | |||||
assertEquals(3, generatedFiles.size()); | assertEquals(3, generatedFiles.size()); | ||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
Map<String, Class<?>> loadedClasses = classLoader.loadClasses(new ArrayList<>(generatedFiles)); | |||||
Map<String, Class<?>> loadedClasses = new JavaFileObjectClassLoader().load(generatedFiles); | |||||
Class<?> clazz = loadedClasses.get("test.WhazzupGreeting"); | Class<?> clazz = loadedClasses.get("test.WhazzupGreeting"); | ||||
Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz); | Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz); | ||||
assertNull(extension); | |||||
} | |||||
static class JavaFileObjectClassLoader extends ClassLoader { | |||||
public Map<String, Class<?>> loadClasses(List<JavaFileObject> classes) throws IOException { | |||||
// Sort generated ".class" by lastModified field | |||||
classes.sort(Comparator.comparingLong(JavaFileObject::getLastModified)); | |||||
// Load classes | |||||
Map<String, Class<?>> loadedClasses = new HashMap<>(classes.size()); | |||||
for (JavaFileObject clazz : classes) { | |||||
String className = getClassName(clazz); | |||||
byte[] data = ByteStreams.toByteArray(clazz.openInputStream()); | |||||
Class<?> loadedClass = defineClass(className, data,0, data.length); | |||||
loadedClasses.put(className, loadedClass); | |||||
} | |||||
return loadedClasses; | |||||
} | |||||
private static String getClassName(JavaFileObject object) { | |||||
String name = object.getName(); | |||||
// Remove "/CLASS_OUT/" from head and ".class" from tail | |||||
name = name.substring(14, name.length() - 6); | |||||
name = name.replace('/', '.'); | |||||
return name; | |||||
} | |||||
Assertions.assertNull(extension); | |||||
} | } | ||||
} | } |
*/ | */ | ||||
package org.pf4j; | package org.pf4j; | ||||
import com.google.testing.compile.JavaFileObjects; | |||||
import org.junit.jupiter.api.AfterEach; | import org.junit.jupiter.api.AfterEach; | ||||
import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||
import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||
import org.pf4j.test.FailTestExtension; | |||||
import org.pf4j.test.JavaFileObjectClassLoader; | |||||
import org.pf4j.test.JavaSources; | |||||
import org.pf4j.test.TestExtension; | import org.pf4j.test.TestExtension; | ||||
import javax.tools.JavaFileObject; | |||||
import static org.junit.jupiter.api.Assertions.assertNotNull; | import static org.junit.jupiter.api.Assertions.assertNotNull; | ||||
import static org.junit.jupiter.api.Assertions.assertThrows; | import static org.junit.jupiter.api.Assertions.assertThrows; | ||||
*/ | */ | ||||
public class DefaultExtensionFactoryTest { | public class DefaultExtensionFactoryTest { | ||||
public static final JavaFileObject FailTestExtension = JavaFileObjects.forSourceLines("FailTestExtension", | |||||
"package test;", | |||||
"import org.pf4j.test.TestExtensionPoint;", | |||||
"import org.pf4j.Extension;", | |||||
"", | |||||
"@Extension", | |||||
"public class FailTestExtension implements TestExtensionPoint {", | |||||
" public FailTestExtension(String name) {}", | |||||
"", | |||||
" @Override", | |||||
" public String saySomething() { return \"I am a fail test extension\";}", | |||||
"}"); | |||||
private ExtensionFactory extensionFactory; | private ExtensionFactory extensionFactory; | ||||
@BeforeEach | @BeforeEach | ||||
*/ | */ | ||||
@Test | @Test | ||||
public void testCreateFailConstructor() { | public void testCreateFailConstructor() { | ||||
assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(FailTestExtension.class)); | |||||
JavaFileObject object = JavaSources.compile(FailTestExtension); | |||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
Class<?> extensionClass = (Class<?>) classLoader.load(object).values().toArray()[0]; | |||||
assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(extensionClass)); | |||||
} | } | ||||
} | } |
*/ | */ | ||||
package org.pf4j; | package org.pf4j; | ||||
import com.google.testing.compile.JavaFileObjects; | |||||
import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||
import org.pf4j.test.AnotherFailTestPlugin; | |||||
import org.pf4j.test.AnotherTestPlugin; | |||||
import org.pf4j.test.FailTestPlugin; | |||||
import org.pf4j.test.JavaFileObjectClassLoader; | |||||
import org.pf4j.test.JavaFileObjectUtils; | |||||
import org.pf4j.test.JavaSources; | |||||
import org.pf4j.test.TestPlugin; | import org.pf4j.test.TestPlugin; | ||||
import javax.tools.JavaFileObject; | |||||
import static org.hamcrest.CoreMatchers.instanceOf; | import static org.hamcrest.CoreMatchers.instanceOf; | ||||
import static org.hamcrest.MatcherAssert.assertThat; | import static org.hamcrest.MatcherAssert.assertThat; | ||||
import static org.junit.jupiter.api.Assertions.assertEquals; | |||||
import static org.junit.jupiter.api.Assertions.assertNotNull; | import static org.junit.jupiter.api.Assertions.assertNotNull; | ||||
import static org.junit.jupiter.api.Assertions.assertNull; | import static org.junit.jupiter.api.Assertions.assertNull; | ||||
import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||
*/ | */ | ||||
public class DefaultPluginFactoryTest { | public class DefaultPluginFactoryTest { | ||||
public static final JavaFileObject FailTestPlugin = JavaFileObjects.forSourceLines("FailTestPlugin", | |||||
"package test;", | |||||
"import org.pf4j.Plugin;", | |||||
"", | |||||
"public class FailTestPlugin {", | |||||
"}"); | |||||
public static final JavaFileObject AnotherFailTestPlugin = JavaFileObjects.forSourceLines("AnotherFailTestPlugin", | |||||
"package test;", | |||||
"import org.pf4j.Plugin;", | |||||
"", | |||||
"public class AnotherFailTestPlugin extends Plugin {", | |||||
" public AnotherFailTestPlugin() { super(null); }", | |||||
"}"); | |||||
public static final JavaFileObject AnotherTestPlugin = JavaFileObjects.forSourceLines("AnotherTestPlugin", | |||||
"package test;", | |||||
"import org.pf4j.Plugin;", | |||||
"", | |||||
"public class AnotherTestPlugin extends Plugin {", | |||||
" public AnotherTestPlugin() { super(); }", | |||||
"}"); | |||||
@Test | @Test | ||||
public void testCreate() { | public void testCreate() { | ||||
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | ||||
@Test | @Test | ||||
public void pluginConstructorNoParameters() { | public void pluginConstructorNoParameters() { | ||||
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | ||||
when(pluginDescriptor.getPluginClass()).thenReturn(AnotherTestPlugin.class.getName()); | |||||
JavaFileObject object = JavaSources.compile(AnotherTestPlugin); | |||||
String pluginClassName = JavaFileObjectUtils.getClassName(object); | |||||
when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName); | |||||
PluginWrapper pluginWrapper = mock(PluginWrapper.class); | PluginWrapper pluginWrapper = mock(PluginWrapper.class); | ||||
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | ||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader()); | |||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
classLoader.load(AnotherTestPlugin); | |||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader); | |||||
PluginFactory pluginFactory = new DefaultPluginFactory(); | PluginFactory pluginFactory = new DefaultPluginFactory(); | ||||
Plugin result = pluginFactory.create(pluginWrapper); | Plugin result = pluginFactory.create(pluginWrapper); | ||||
assertNotNull(result); | assertNotNull(result); | ||||
assertThat(result, instanceOf(AnotherTestPlugin.class)); | |||||
assertEquals(pluginClassName, result.getClass().getName()); | |||||
} | } | ||||
@Test | @Test | ||||
public void testCreateFail() { | public void testCreateFail() { | ||||
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | ||||
when(pluginDescriptor.getPluginClass()).thenReturn(FailTestPlugin.class.getName()); | |||||
JavaFileObject object = JavaSources.compile(FailTestPlugin); | |||||
String pluginClassName = JavaFileObjectUtils.getClassName(object); | |||||
when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName); | |||||
PluginWrapper pluginWrapper = mock(PluginWrapper.class); | PluginWrapper pluginWrapper = mock(PluginWrapper.class); | ||||
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | ||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader()); | |||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
classLoader.load(FailTestPlugin); | |||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader); | |||||
PluginFactory pluginFactory = new DefaultPluginFactory(); | PluginFactory pluginFactory = new DefaultPluginFactory(); | ||||
@Test | @Test | ||||
public void testCreateFailConstructor() { | public void testCreateFailConstructor() { | ||||
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class); | ||||
when(pluginDescriptor.getPluginClass()).thenReturn(AnotherFailTestPlugin.class.getName()); | |||||
JavaFileObject object = JavaSources.compile(AnotherFailTestPlugin); | |||||
String pluginClassName = JavaFileObjectUtils.getClassName(object); | |||||
when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName); | |||||
PluginWrapper pluginWrapper = mock(PluginWrapper.class); | PluginWrapper pluginWrapper = mock(PluginWrapper.class); | ||||
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor); | ||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader()); | |||||
JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader(); | |||||
classLoader.load(AnotherFailTestPlugin); | |||||
when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader); | |||||
PluginFactory pluginFactory = new DefaultPluginFactory(); | PluginFactory pluginFactory = new DefaultPluginFactory(); | ||||
package org.pf4j; | package org.pf4j; | ||||
import com.google.testing.compile.Compilation; | import com.google.testing.compile.Compilation; | ||||
import com.google.testing.compile.Compiler; | |||||
import com.google.testing.compile.JavaFileObjects; | import com.google.testing.compile.JavaFileObjects; | ||||
import org.junit.jupiter.api.BeforeEach; | |||||
import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||
import org.pf4j.processor.ExtensionAnnotationProcessor; | import org.pf4j.processor.ExtensionAnnotationProcessor; | ||||
import org.pf4j.processor.LegacyExtensionStorage; | import org.pf4j.processor.LegacyExtensionStorage; | ||||
import org.pf4j.test.JavaSources; | |||||
import javax.tools.JavaFileObject; | import javax.tools.JavaFileObject; | ||||
import java.io.IOException; | |||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
import java.util.HashSet; | import java.util.HashSet; | ||||
*/ | */ | ||||
public class ExtensionAnnotationProcessorTest { | public class ExtensionAnnotationProcessorTest { | ||||
public static final JavaFileObject Greeting = JavaFileObjects.forSourceLines( | |||||
"Greeting", | |||||
"package test;", | |||||
"import org.pf4j.ExtensionPoint;", | |||||
"", | |||||
"public interface Greeting extends ExtensionPoint {", | |||||
" String getGreeting();", | |||||
"}"); | |||||
public static final JavaFileObject WhazzupGreeting = JavaFileObjects.forSourceLines( | |||||
"WhazzupGreeting", | |||||
"package test;", | |||||
"import org.pf4j.Extension;", | |||||
"", | |||||
"@Extension", | |||||
"public class WhazzupGreeting implements Greeting {", | |||||
" @Override", | |||||
" public String getGreeting() {", | |||||
" return \"Whazzup\";", | |||||
" }", | |||||
"}"); | |||||
public static final JavaFileObject WhazzupGreeting_NoExtensionPoint = JavaFileObjects.forSourceLines( | |||||
"WhazzupGreeting", | |||||
public static final JavaFileObject WhazzupGreeting_NoExtensionPoint = JavaFileObjects.forSourceLines("WhazzupGreeting", | |||||
"package test;", | "package test;", | ||||
"import org.pf4j.Extension;", | "import org.pf4j.Extension;", | ||||
"", | "", | ||||
" }", | " }", | ||||
"}"); | "}"); | ||||
public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines( | |||||
"SpinnakerExtension", | |||||
public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines("SpinnakerExtension", | |||||
"package test;", | "package test;", | ||||
"", | "", | ||||
"import org.pf4j.Extension;", | "import org.pf4j.Extension;", | ||||
"public @interface SpinnakerExtension {", | "public @interface SpinnakerExtension {", | ||||
"}"); | "}"); | ||||
public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines( | |||||
"WhazzupGreeting", | |||||
public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines("WhazzupGreeting", | |||||
"package test;", | "package test;", | ||||
"", | "", | ||||
"@SpinnakerExtension", | "@SpinnakerExtension", | ||||
"}"); | "}"); | ||||
/** | /** | ||||
* The same like {@link #SpinnakerExtension} but without {@code Extension} annotation. | |||||
* The same as {@link #SpinnakerExtension} but without {@code Extension} annotation. | |||||
*/ | */ | ||||
public static final JavaFileObject SpinnakerExtension_NoExtension = JavaFileObjects.forSourceLines( | |||||
"SpinnakerExtension", | |||||
public static final JavaFileObject SpinnakerExtension_NoExtension = JavaFileObjects.forSourceLines("SpinnakerExtension", | |||||
"package test;", | "package test;", | ||||
"", | "", | ||||
"import org.pf4j.Extension;", | "import org.pf4j.Extension;", | ||||
"public @interface SpinnakerExtension {", | "public @interface SpinnakerExtension {", | ||||
"}"); | "}"); | ||||
private ExtensionAnnotationProcessor annotationProcessor; | |||||
@BeforeEach | |||||
public void setUp() throws IOException { | |||||
annotationProcessor = new ExtensionAnnotationProcessor(); | |||||
} | |||||
@Test | @Test | ||||
public void getSupportedAnnotationTypes() { | public void getSupportedAnnotationTypes() { | ||||
ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor(); | |||||
Set<String> result = instance.getSupportedAnnotationTypes(); | |||||
Set<String> result = annotationProcessor.getSupportedAnnotationTypes(); | |||||
assertEquals(1, result.size()); | assertEquals(1, result.size()); | ||||
assertEquals("*", result.iterator().next()); | assertEquals("*", result.iterator().next()); | ||||
} | } | ||||
@Test | @Test | ||||
public void getSupportedOptions() { | public void getSupportedOptions() { | ||||
ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor(); | |||||
Set<String> result = instance.getSupportedOptions(); | |||||
Set<String> result = annotationProcessor.getSupportedOptions(); | |||||
assertEquals(2, result.size()); | assertEquals(2, result.size()); | ||||
} | } | ||||
@Test | @Test | ||||
public void options() { | public void options() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).withOptions("-Ab=2", "-Ac=3") | |||||
.compile(Greeting, WhazzupGreeting); | |||||
assertEquals(compilation.status(), Compilation.Status.SUCCESS); | |||||
Compilation compilation = compiler().withOptions("-Ab=2", "-Ac=3") | |||||
.compile(JavaSources.Greeting, JavaSources.WhazzupGreeting); | |||||
assertEquals(Compilation.Status.SUCCESS, compilation.status()); | |||||
Map<String, String> options = new HashMap<>(); | Map<String, String> options = new HashMap<>(); | ||||
options.put("b", "2"); | options.put("b", "2"); | ||||
options.put("c", "3"); | options.put("c", "3"); | ||||
assertEquals(options, processor.getProcessingEnvironment().getOptions()); | |||||
assertEquals(options, annotationProcessor.getProcessingEnvironment().getOptions()); | |||||
} | } | ||||
@Test | @Test | ||||
public void storage() { | public void storage() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting); | |||||
assertEquals(compilation.status(), Compilation.Status.SUCCESS); | |||||
assertEquals(processor.getStorage().getClass(), LegacyExtensionStorage.class); | |||||
Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting); | |||||
assertEquals(Compilation.Status.SUCCESS, compilation.status()); | |||||
assertEquals(annotationProcessor.getStorage().getClass(), LegacyExtensionStorage.class); | |||||
} | } | ||||
@Test | @Test | ||||
public void compileWithoutError() { | public void compileWithoutError() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting); | |||||
Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting); | |||||
assertThat(compilation).succeededWithoutWarnings(); | assertThat(compilation).succeededWithoutWarnings(); | ||||
} | } | ||||
@Test | @Test | ||||
public void compileWithError() { | public void compileWithError() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting_NoExtensionPoint); | |||||
Compilation compilation = compile(JavaSources.Greeting, WhazzupGreeting_NoExtensionPoint); | |||||
assertThat(compilation).failed(); | assertThat(compilation).failed(); | ||||
assertThat(compilation).hadErrorContaining("it doesn't implement ExtensionPoint") | assertThat(compilation).hadErrorContaining("it doesn't implement ExtensionPoint") | ||||
.inFile(WhazzupGreeting_NoExtensionPoint) | .inFile(WhazzupGreeting_NoExtensionPoint) | ||||
@Test | @Test | ||||
public void getExtensions() { | public void getExtensions() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting); | |||||
Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting); | |||||
assertThat(compilation).succeededWithoutWarnings(); | assertThat(compilation).succeededWithoutWarnings(); | ||||
Map<String, Set<String>> extensions = new HashMap<>(); | Map<String, Set<String>> extensions = new HashMap<>(); | ||||
extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting"))); | extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting"))); | ||||
assertEquals(extensions, processor.getExtensions()); | |||||
assertEquals(extensions, annotationProcessor.getExtensions()); | |||||
} | } | ||||
@Test | @Test | ||||
public void compileNestedExtensionAnnotation() { | public void compileNestedExtensionAnnotation() { | ||||
ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor(); | |||||
Compilation compilation = javac().withProcessors(processor).compile(Greeting, SpinnakerExtension, WhazzupGreeting_SpinnakerExtension); | |||||
Compilation compilation = compile(JavaSources.Greeting, SpinnakerExtension, WhazzupGreeting_SpinnakerExtension); | |||||
assertThat(compilation).succeededWithoutWarnings(); | assertThat(compilation).succeededWithoutWarnings(); | ||||
Map<String, Set<String>> extensions = new HashMap<>(); | Map<String, Set<String>> extensions = new HashMap<>(); | ||||
extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting"))); | extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting"))); | ||||
assertEquals(extensions, processor.getExtensions()); | |||||
assertEquals(extensions, annotationProcessor.getExtensions()); | |||||
} | |||||
private Compiler compiler() { | |||||
return javac().withProcessors(annotationProcessor); | |||||
} | |||||
private Compilation compile(JavaFileObject... sources) { | |||||
return compiler().compile(sources); | |||||
} | } | ||||
} | } |
import org.junit.jupiter.api.AfterEach; | import org.junit.jupiter.api.AfterEach; | ||||
import org.junit.jupiter.api.BeforeEach; | import org.junit.jupiter.api.BeforeEach; | ||||
import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||
import org.pf4j.test.FailTestExtension; | |||||
import org.pf4j.test.TestExtension; | import org.pf4j.test.TestExtension; | ||||
import java.io.File; | import java.io.File; | ||||
@Test | @Test | ||||
public void createNewEachTime() { | public void createNewEachTime() { | ||||
ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, FailTestExtension.class.getName()); | |||||
ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, "FailTestExtension.class"); | |||||
Object extensionOne = extensionFactory.create(TestExtension.class); | Object extensionOne = extensionFactory.create(TestExtension.class); | ||||
Object extensionTwo = extensionFactory.create(TestExtension.class); | Object extensionTwo = extensionFactory.create(TestExtension.class); | ||||
assertNotSame(extensionOne, extensionTwo); | assertNotSame(extensionOne, extensionTwo); |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import org.pf4j.Plugin; | |||||
/** | |||||
* A wrong {@link org.pf4j.Plugin}. | |||||
* It's wrong because it calls super constructor with {@code null} for ({@link org.pf4j.PluginWrapper} parameter). | |||||
* | |||||
* @author Mario Franco | |||||
*/ | |||||
public class AnotherFailTestPlugin extends Plugin { | |||||
public AnotherFailTestPlugin() { | |||||
super(null); | |||||
} | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import org.pf4j.Plugin; | |||||
/** | |||||
* A simple {@link Plugin}. | |||||
* | |||||
* In real applications you don't need to create a plugin like this if you are not interested in lifecycle events. | |||||
* {@code PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified. | |||||
* | |||||
* @author Decebal Suiu | |||||
*/ | |||||
public class AnotherTestPlugin extends Plugin { | |||||
public AnotherTestPlugin() { | |||||
super(); | |||||
} | |||||
} |
*/ | */ | ||||
package org.pf4j.test; | package org.pf4j.test; | ||||
import java.io.ByteArrayOutputStream; | |||||
import com.google.common.io.ByteStreams; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.io.InputStream; | import java.io.InputStream; | ||||
import java.io.OutputStream; | |||||
/** | /** | ||||
* Get class data from the class path. | * Get class data from the class path. | ||||
throw new RuntimeException("Cannot find class data"); | throw new RuntimeException("Cannot find class data"); | ||||
} | } | ||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { | |||||
copyStream(classDataStream, outputStream); | |||||
return outputStream.toByteArray(); | |||||
try { | |||||
return ByteStreams.toByteArray(classDataStream); | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
throw new RuntimeException(e.getMessage(), e); | |||||
} | |||||
} | |||||
private void copyStream(InputStream in, OutputStream out) throws IOException { | |||||
byte[] buffer = new byte[1024]; | |||||
int bytesRead; | |||||
while ((bytesRead = in.read(buffer)) != -1) { | |||||
out.write(buffer, 0, bytesRead); | |||||
throw new IllegalStateException(e); | |||||
} | } | ||||
} | } | ||||
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import org.pf4j.Extension; | |||||
/** | |||||
* A wrong {@link org.pf4j.Extension}. | |||||
* It's wrong because it doesn't contain a constructor with empty parameters (or only the default constructor). | |||||
* | |||||
* @author Mario Franco | |||||
*/ | |||||
@Extension | |||||
public class FailTestExtension implements TestExtensionPoint { | |||||
public FailTestExtension(String name) { | |||||
} | |||||
@Override | |||||
public String saySomething() { | |||||
return "I am a fail test extension"; | |||||
} | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
/** | |||||
* A wrong {@link org.pf4j.Plugin}. | |||||
* It's wrong because it doesn't extends {@link org.pf4j.Plugin}. | |||||
* | |||||
* @author Mario Franco | |||||
*/ | |||||
public class FailTestPlugin { | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import javax.tools.JavaFileObject; | |||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.Comparator; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.Objects; | |||||
/** | |||||
* {@link ClassLoader} that loads {@link JavaFileObject.Kind#CLASS}s. | |||||
* If {@code JavaFileObject} type is {@link JavaFileObject.Kind#SOURCE} them the source is compiled. | |||||
* | |||||
* @author Decebal Suiu | |||||
*/ | |||||
public class JavaFileObjectClassLoader extends ClassLoader { | |||||
public Map<String, Class<?>> load(JavaFileObject... objects) { | |||||
return load(Arrays.asList(objects)); | |||||
} | |||||
public Map<String, Class<?>> load(List<JavaFileObject> objects) { | |||||
Objects.requireNonNull(objects); | |||||
List<JavaFileObject> mutableObjects = new ArrayList<>(objects); | |||||
// Sort generated ".class" by lastModified field | |||||
mutableObjects.sort(Comparator.comparingLong(JavaFileObject::getLastModified)); | |||||
// Compile Java sources (if exists) | |||||
for (int i = 0; i < mutableObjects.size(); i++) { | |||||
JavaFileObject object = mutableObjects.get(i); | |||||
if (object.getKind() == JavaFileObject.Kind.CLASS) { | |||||
continue; | |||||
} | |||||
if (object.getKind() == JavaFileObject.Kind.SOURCE) { | |||||
mutableObjects.set(i, JavaSources.compile(object)); | |||||
} else { | |||||
throw new IllegalStateException("Type " + object.getKind() + " is not supported"); | |||||
} | |||||
} | |||||
// Load objects | |||||
Map<String, Class<?>> loadedClasses = new HashMap<>(); | |||||
for (JavaFileObject object : mutableObjects) { | |||||
String className = JavaFileObjectUtils.getClassName(object); | |||||
byte[] data = JavaFileObjectUtils.getAllBytes(object); | |||||
Class<?> loadedClass = defineClass(className, data, 0, data.length); | |||||
loadedClasses.put(className, loadedClass); | |||||
} | |||||
return loadedClasses; | |||||
} | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import javax.tools.FileObject; | |||||
import javax.tools.JavaFileObject; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
import java.util.stream.Collectors; | |||||
/** | |||||
* Get class data from {@link JavaFileObject}. | |||||
* If {@code JavaFileObject} type is {@link JavaFileObject.Kind#SOURCE} them the source is compiled. | |||||
* | |||||
* @author Decebal Suiu | |||||
*/ | |||||
public class JavaFileObjectDataProvider implements ClassDataProvider { | |||||
private final Map<String, JavaFileObject> classes; | |||||
public JavaFileObjectDataProvider(Map<String, JavaFileObject> classes) { | |||||
this.classes = classes; | |||||
} | |||||
public static JavaFileObjectDataProvider of(List<JavaFileObject> objects) { | |||||
List<JavaFileObject> tmp = new ArrayList<>(objects.size()); | |||||
for (JavaFileObject object : objects) { | |||||
if (object.getKind() == JavaFileObject.Kind.CLASS) { | |||||
tmp.add(object); | |||||
} else if (object.getKind() == JavaFileObject.Kind.SOURCE) { | |||||
tmp.add(JavaSources.compile(object)); | |||||
} else { | |||||
throw new IllegalStateException("Type " + object.getKind() + " is not supported"); | |||||
} | |||||
} | |||||
// TODO JavaFileObjectUtils.getClassName() ?! | |||||
Map<String, JavaFileObject> classes = tmp.stream().collect(Collectors.toMap(FileObject::getName, c -> c)); | |||||
return new JavaFileObjectDataProvider(classes); | |||||
} | |||||
@Override | |||||
public byte[] getClassData(String className) { | |||||
return JavaFileObjectUtils.getAllBytes(classes.get(className)); | |||||
} | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import com.google.common.io.ByteStreams; | |||||
import javax.tools.JavaFileObject; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
/** | |||||
* @author Decebal Suiu | |||||
*/ | |||||
public class JavaFileObjectUtils { | |||||
private JavaFileObjectUtils() {} | |||||
public static String getClassName(JavaFileObject object) { | |||||
if (object.getKind() != JavaFileObject.Kind.CLASS) { | |||||
throw new IllegalStateException("Only Kind.CLASS is supported"); | |||||
} | |||||
String name = object.getName(); | |||||
// Remove "/CLASS_OUT/" from head and ".class" from tail | |||||
name = name.substring(14, name.length() - 6); | |||||
name = name.replace('/', '.'); | |||||
return name; | |||||
} | |||||
public static byte[] getAllBytes(JavaFileObject object) { | |||||
try (InputStream in = object.openInputStream()) { | |||||
return ByteStreams.toByteArray(in); | |||||
} catch (IOException e) { | |||||
throw new IllegalStateException(e); | |||||
} | |||||
} | |||||
} |
/* | |||||
* Copyright (C) 2012-present the original author or authors. | |||||
* | |||||
* Licensed 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.pf4j.test; | |||||
import com.google.testing.compile.JavaFileObjects; | |||||
import javax.tools.JavaFileObject; | |||||
import java.util.List; | |||||
import static com.google.testing.compile.Compiler.javac; | |||||
/** | |||||
* Keep common Java sources (useful in many tests). | |||||
* For Java 13+ is recommended to use Text Block feature (it's more clear). | |||||
* | |||||
* @author Decebal Suiu | |||||
*/ | |||||
public class JavaSources { | |||||
public static final JavaFileObject Greeting = JavaFileObjects.forSourceLines("Greeting", | |||||
"package test;", | |||||
"import org.pf4j.ExtensionPoint;", | |||||
"", | |||||
"public interface Greeting extends ExtensionPoint {", | |||||
" String getGreeting();", | |||||
"}"); | |||||
public static final JavaFileObject WhazzupGreeting = JavaFileObjects.forSourceLines("WhazzupGreeting", | |||||
"package test;", | |||||
"import org.pf4j.Extension;", | |||||
"", | |||||
"@Extension", | |||||
"public class WhazzupGreeting implements Greeting {", | |||||
" @Override", | |||||
" public String getGreeting() {", | |||||
" return \"Whazzup\";", | |||||
" }", | |||||
"}"); | |||||
/** | |||||
* Compile a list of sources using javac compiler. | |||||
*/ | |||||
public static List<JavaFileObject> compileAll(JavaFileObject... sources) { | |||||
return javac().compile(sources).generatedFiles(); | |||||
} | |||||
public static JavaFileObject compile(JavaFileObject source) { | |||||
return compileAll(source).get(0); | |||||
} | |||||
} |
/** | /** | ||||
* A simple {@link Plugin}. | * A simple {@link Plugin}. | ||||
* | |||||
* In real applications you don't need to create a plugin like this if you are not interested in lifecycle events. | * In real applications you don't need to create a plugin like this if you are not interested in lifecycle events. | ||||
* {@codes PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified. | |||||
* {@code PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified. | |||||
* | * | ||||
* @author Mario Franco | * @author Mario Franco | ||||
*/ | */ |