*/
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.Assertions;
import org.junit.jupiter.api.BeforeEach;
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 javax.tools.JavaFileObject;
-import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
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.assertNotNull;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
when(pluginStopped.getPluginState()).thenReturn(PluginState.STOPPED);
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());
}
}
};
- List<ExtensionWrapper<FailTestPlugin>> list = instance.find(FailTestPlugin.class);
+ List<ExtensionWrapper<TestExtension>> list = instance.find(TestExtension.class);
assertEquals(0, list.size());
}
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put(null, bucket);
return entries;
};
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
}
/**
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put("plugin1", bucket);
bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
};
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
list = instance.find(TestExtensionPoint.class, "plugin1");
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
list = instance.find(TestExtensionPoint.class, "plugin2");
+ // "0" because the status of "plugin2" is STOPPED => no extensions
assertEquals(0, list.size());
}
*/
@Test
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) {
@Override
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put("plugin1", bucket);
bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
entries.put("plugin2", bucket);
+ bucket = new HashSet<>();
+ bucket.add(JavaFileObjectUtils.getClassName(object));
+ entries.put("plugin3", bucket);
return entries;
}
};
List<ExtensionWrapper> plugin1Result = instance.find("plugin1");
- assertEquals(2, plugin1Result.size());
+ assertEquals(1, plugin1Result.size());
List<ExtensionWrapper> plugin2Result = instance.find("plugin2");
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
- 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());
- 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");
Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz);
- assertNotNull(extension);
+ Assertions.assertNotNull(extension);
}
@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.WhazzupGreeting_SpinnakerExtension);
- assertThat(compilation).succeededWithoutWarnings();
- ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles();
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");
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;
+import com.google.testing.compile.JavaFileObjects;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
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 javax.tools.JavaFileObject;
+
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
*/
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;
@BeforeEach
*/
@Test
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;
+import com.google.testing.compile.JavaFileObjects;
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 javax.tools.JavaFileObject;
+
import static org.hamcrest.CoreMatchers.instanceOf;
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.assertNull;
import static org.mockito.Mockito.mock;
*/
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
public void testCreate() {
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
@Test
public void pluginConstructorNoParameters() {
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);
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();
Plugin result = pluginFactory.create(pluginWrapper);
assertNotNull(result);
- assertThat(result, instanceOf(AnotherTestPlugin.class));
+ assertEquals(pluginClassName, result.getClass().getName());
}
@Test
public void testCreateFail() {
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);
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();
@Test
public void testCreateFailConstructor() {
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);
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();
package org.pf4j;
import com.google.testing.compile.Compilation;
+import com.google.testing.compile.Compiler;
import com.google.testing.compile.JavaFileObjects;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pf4j.processor.ExtensionAnnotationProcessor;
import org.pf4j.processor.LegacyExtensionStorage;
+import org.pf4j.test.JavaSources;
import javax.tools.JavaFileObject;
+import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
*/
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;",
"import org.pf4j.Extension;",
"",
" }",
"}");
- public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines(
- "SpinnakerExtension",
+ public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines("SpinnakerExtension",
"package test;",
"",
"import org.pf4j.Extension;",
"public @interface SpinnakerExtension {",
"}");
- public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines(
- "WhazzupGreeting",
+ public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines("WhazzupGreeting",
"package test;",
"",
"@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;",
"",
"import org.pf4j.Extension;",
"public @interface SpinnakerExtension {",
"}");
+ private ExtensionAnnotationProcessor annotationProcessor;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ annotationProcessor = new ExtensionAnnotationProcessor();
+ }
+
@Test
public void getSupportedAnnotationTypes() {
- ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor();
- Set<String> result = instance.getSupportedAnnotationTypes();
+ Set<String> result = annotationProcessor.getSupportedAnnotationTypes();
assertEquals(1, result.size());
assertEquals("*", result.iterator().next());
}
@Test
public void getSupportedOptions() {
- ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor();
- Set<String> result = instance.getSupportedOptions();
+ Set<String> result = annotationProcessor.getSupportedOptions();
assertEquals(2, result.size());
}
@Test
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<>();
options.put("b", "2");
options.put("c", "3");
- assertEquals(options, processor.getProcessingEnvironment().getOptions());
+ assertEquals(options, annotationProcessor.getProcessingEnvironment().getOptions());
}
@Test
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
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();
}
@Test
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).hadErrorContaining("it doesn't implement ExtensionPoint")
.inFile(WhazzupGreeting_NoExtensionPoint)
@Test
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();
Map<String, Set<String>> extensions = new HashMap<>();
extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting")));
- assertEquals(extensions, processor.getExtensions());
+ assertEquals(extensions, annotationProcessor.getExtensions());
}
@Test
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();
Map<String, Set<String>> extensions = new HashMap<>();
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.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.pf4j.test.FailTestExtension;
import org.pf4j.test.TestExtension;
import java.io.File;
@Test
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 extensionTwo = extensionFactory.create(TestExtension.class);
assertNotSame(extensionOne, extensionTwo);
+++ /dev/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 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);
- }
-
-}
+++ /dev/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;
-import java.io.ByteArrayOutputStream;
+import com.google.common.io.ByteStreams;
+
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
* Get class data from the class path.
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) {
- 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);
}
}
+++ /dev/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.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";
- }
-
-}
+++ /dev/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;
-
-/**
- * A wrong {@link org.pf4j.Plugin}.
- * It's wrong because it doesn't extends {@link org.pf4j.Plugin}.
- *
- * @author Mario Franco
- */
-public class FailTestPlugin {
-
-}
--- /dev/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 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;
+ }
+
+}
--- /dev/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 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));
+ }
+
+}
--- /dev/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 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);
+ }
+ }
+
+}
--- /dev/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 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}.
- *
* 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
*/