This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
commit 2792d6e819cc8417f241fc7857988e1a7b3ec7e3 Author: Andi Huber <ahu...@apache.org> AuthorDate: Sun May 20 10:00:03 2018 +0200 ISIS-1948: provides a means to load plugins not initially on classpath Task-Url: https://issues.apache.org/jira/browse/ISIS-1948 --- .../isis/commons/internal/context/_Plugin.java | 50 ++++++++++++++++ core/plugins/codegen-javassist/pom.xml | 2 +- .../codegen/ProxyFactoryPluginUsingJavassist.java | 5 +- .../jmocking/JavassistImposteriser.java | 0 .../jmocking/JavassistImposteriserTest.java | 0 core/unittestsupport/pom.xml | 21 ++++--- .../jmocking/JUnitRuleMockery2.java | 2 +- ...riserTest.java => DefaultImposteriserTest.java} | 69 ++++++++++++++++------ 8 files changed, 118 insertions(+), 31 deletions(-) diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/context/_Plugin.java b/core/commons/src/main/java/org/apache/isis/commons/internal/context/_Plugin.java index c2ac726..d9c5152 100644 --- a/core/commons/src/main/java/org/apache/isis/commons/internal/context/_Plugin.java +++ b/core/commons/src/main/java/org/apache/isis/commons/internal/context/_Plugin.java @@ -19,13 +19,18 @@ package org.apache.isis.commons.internal.context; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; import java.util.Objects; import java.util.ServiceLoader; import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.apache.isis.commons.internal.base._Casts; import org.apache.isis.commons.internal.base._NullSafe; import org.apache.isis.commons.internal.collections._Sets; import org.apache.isis.core.plugins.PluginResolveException; @@ -142,6 +147,51 @@ public final class _Plugin { pluginInterfaceClass.getName() )); } + // -- JUNIT TEST SUPPORT + /** + * TODO will break with java 9+ + * @return file-system path, where the frameworks core classes reside (after a build). + */ + public static URL getCoreCommonsTargetFolder() { + return Stream.of(((URLClassLoader )_Plugin.class.getClassLoader()).getURLs()) + .filter(url->url.toString().contains("/core/commons/")) + .findFirst() + .orElseThrow(()->new RuntimeException("Failed to find file-system path, where the frameworks core classes reside.")) + ; + } + + /** + * Loads a plugin by name and class-path. (Most likely used by JUnit Tests.) + * @param pluginClass + * @param classPath + * @param pluginFullyQualifiedClassName + * @return + */ + public static <S> S load(Class<S> pluginInterfaceClass, File classPath, String pluginFullyQualifiedClassName) { + + try { + + ClassLoader parentCL = pluginInterfaceClass.getClassLoader(); + URL[] urls = {classPath.toURI().toURL()}; + ClassLoader cl = URLClassLoader.newInstance(urls, parentCL); + Class<S> pluginClass = _Casts.uncheckedCast( + cl.loadClass(pluginFullyQualifiedClassName)); + S plugin = pluginClass.newInstance(); + + _Context.putSingleton(pluginInterfaceClass, plugin); + + return plugin; + + } catch (Exception e) { + throw new PluginResolveException( + String.format("Failed to load plugin '%s' implementing '%s' from path '%s'.", + pluginFullyQualifiedClassName, + pluginInterfaceClass.getName(), + classPath.getAbsolutePath() + ), e); + } + + } } diff --git a/core/plugins/codegen-javassist/pom.xml b/core/plugins/codegen-javassist/pom.xml index a0f7382..2e5cf62 100644 --- a/core/plugins/codegen-javassist/pom.xml +++ b/core/plugins/codegen-javassist/pom.xml @@ -67,7 +67,7 @@ <dependency> <groupId>org.apache.isis.core</groupId> - <artifactId>isis-core-runtime</artifactId> + <artifactId>isis-core-commons</artifactId> <scope>compile</scope> </dependency> diff --git a/core/plugins/codegen-javassist/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingJavassist.java b/core/plugins/codegen-javassist/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingJavassist.java index 5132a66..5247b3d 100644 --- a/core/plugins/codegen-javassist/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingJavassist.java +++ b/core/plugins/codegen-javassist/src/main/java/org/apache/isis/core/plugins/codegen/ProxyFactoryPluginUsingJavassist.java @@ -10,7 +10,6 @@ import javax.annotation.Nullable; import org.apache.isis.commons.internal._Constants; import org.apache.isis.commons.internal.base._Casts; import org.apache.isis.commons.internal.base._NullSafe; -import org.apache.isis.core.commons.exceptions.IsisException; import org.apache.isis.core.plugins.codegen.ProxyFactory; import org.apache.isis.core.plugins.codegen.ProxyFactoryPlugin; import org.objenesis.Objenesis; @@ -53,7 +52,7 @@ public class ProxyFactoryPluginUsingJavassist implements ProxyFactoryPlugin { } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new IsisException(e); + throw new RuntimeException(e); } } @@ -68,7 +67,7 @@ public class ProxyFactoryPluginUsingJavassist implements ProxyFactoryPlugin { return _Casts.uncheckedCast( createUsingConstructor(handler, constructorArgs) ); } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new IsisException(e); + throw new RuntimeException(e); } } diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriser.java b/core/unittestsupport-legacy/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriser.java similarity index 100% rename from core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriser.java rename to core/unittestsupport-legacy/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriser.java diff --git a/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java b/core/unittestsupport-legacy/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java similarity index 100% copy from core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java copy to core/unittestsupport-legacy/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java diff --git a/core/unittestsupport/pom.xml b/core/unittestsupport/pom.xml index 69a5511..de70610 100644 --- a/core/unittestsupport/pom.xml +++ b/core/unittestsupport/pom.xml @@ -40,6 +40,14 @@ <groupId>org.apache.isis.core</groupId> <artifactId>isis-core-commons</artifactId> </dependency> + + <!-- specifically to test the codegen-javassist plugin --> + <dependency> + <groupId>org.javassist</groupId> + <artifactId>javassist</artifactId> + <scope>test</scope> + <optional>true</optional> + </dependency> <dependency> <groupId>junit</groupId> @@ -60,13 +68,7 @@ <groupId>org.jmock</groupId> <artifactId>jmock-junit4</artifactId> </dependency> - - <dependency> - <groupId>org.objenesis</groupId> - <artifactId>objenesis</artifactId> - <optional>true</optional> - </dependency> - + <!-- JDO API (non transient, provided by plugin) --> <dependency> <groupId>javax.jdo</groupId> @@ -86,6 +88,11 @@ <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> </exclusion> + <exclusion> + <!-- provided by plugins if required --> + <groupId>org.javassist</groupId> + <artifactId>javassist</artifactId> + </exclusion> </exclusions> <optional>true</optional> </dependency> diff --git a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JUnitRuleMockery2.java b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JUnitRuleMockery2.java index 0363b41..18db4cf 100644 --- a/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JUnitRuleMockery2.java +++ b/core/unittestsupport/src/main/java/org/apache/isis/core/unittestsupport/jmocking/JUnitRuleMockery2.java @@ -67,7 +67,7 @@ public class JUnitRuleMockery2 extends JUnit4Mockery implements MethodRule { public static JUnitRuleMockery2 createFor(final Mode mode) { final JUnitRuleMockery2 jUnitRuleMockery2 = new JUnitRuleMockery2(); if (mode == Mode.INTERFACES_AND_CLASSES) { - jUnitRuleMockery2.setImposteriser(JavassistImposteriser.INSTANCE); + jUnitRuleMockery2.setImposteriser(Imposterisers.getDefault()); } jUnitRuleMockery2.setThreadingPolicy(new Synchroniser()); return jUnitRuleMockery2; diff --git a/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java b/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/DefaultImposteriserTest.java similarity index 79% rename from core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java rename to core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/DefaultImposteriserTest.java index ab746ee..7563493 100644 --- a/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/JavassistImposteriserTest.java +++ b/core/unittestsupport/src/test/java/org/apache/isis/core/unittestsupport/jmocking/DefaultImposteriserTest.java @@ -18,50 +18,84 @@ */ package org.apache.isis.core.unittestsupport.jmocking; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Paths; import java.util.Date; + +import org.apache.isis.commons.internal.context._Context; +import org.apache.isis.commons.internal.context._Plugin; +import org.apache.isis.core.plugins.codegen.ProxyFactoryPlugin; import org.jmock.api.Imposteriser; import org.jmock.api.Invocation; import org.jmock.api.Invokable; import org.jmock.lib.action.VoidAction; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; +public class DefaultImposteriserTest { -public class JavassistImposteriserTest { - - private Imposteriser imposteriser = JavassistImposteriser.INSTANCE; + private Imposteriser imposteriser = Imposterisers.getDefault(); private Invokable invokable; - private Invocation invocation; - + @SuppressWarnings("unused") + private Invocation invocation; @Before public void setUp() throws Exception { invokable = new Invokable() { @Override public Object invoke(Invocation invocation) throws Throwable { - JavassistImposteriserTest.this.invocation = invocation; + DefaultImposteriserTest.this.invocation = invocation; return "result"; } }; + + // -- loading codegen plugin by name (because not configured as a maven dependency) + { + String pluginFullyQualifiedClassName = "org.apache.isis.core.plugins.codegen.ProxyFactoryPluginUsingJavassist"; + // we are guessing where to find the pluginTarget based on the 'commons' target location + String commonsTarget = + Paths.get(_Plugin.getCoreCommonsTargetFolder().toURI()) + .toFile() + .getCanonicalPath() + .replace('\\', '/'); + ; + String pluginTarget = commonsTarget.replace("/core/commons/", "/core/plugins/codegen-javassist/"); + + _Plugin.load(ProxyFactoryPlugin.class, new File(pluginTarget), pluginFullyQualifiedClassName); + } + + } @After public void tearDown() throws Exception { invokable = null; invocation = null; + _Context.clear(); // removes plugins from context } - // ////////////////////////////////////// + + @Test + public void canLoadCodegenPlugin() throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException { + Assert.assertNotNull(ProxyFactoryPlugin.get()); + } + // ////////////////////////////////////// @Test public void happyCaseWhenJdkInterface() { @@ -97,7 +131,6 @@ public class JavassistImposteriserTest { public static abstract class AnAbstractNestedClass { - @SuppressWarnings("UnusedDeclaration") public abstract String foo(); } @@ -115,7 +148,6 @@ public class JavassistImposteriserTest { public static class AnInnerClass { - @SuppressWarnings("UnusedDeclaration") public String foo() {return "original result";} } @@ -133,7 +165,6 @@ public class JavassistImposteriserTest { public static final class AFinalClass { - @SuppressWarnings("UnusedDeclaration") public String foo() {return "original result";} } @@ -169,7 +200,6 @@ public class JavassistImposteriserTest { - @SuppressWarnings("ClassInitializerMayBeStatic") public static class ConcreteClassWithConstructorAndInstanceInitializer { { shouldNotBeCalled("instance initializer"); @@ -231,13 +261,14 @@ public class JavassistImposteriserTest { assertTrue(jarFile.exists()); URL jarURL = jarFile.toURI().toURL(); - ClassLoader loader = new URLClassLoader(new URL[]{jarURL}); - Class<?> typeInSignedJar = loader.loadClass("TypeInSignedJar"); - - assertTrue(imposteriser.canImposterise(typeInSignedJar)); - Object o = imposteriser.imposterise(new VoidAction(), typeInSignedJar); - - assertTrue(typeInSignedJar.isInstance(o)); + try(URLClassLoader loader = new URLClassLoader(new URL[]{jarURL})){ + Class<?> typeInSignedJar = loader.loadClass("TypeInSignedJar"); + + assertTrue(imposteriser.canImposterise(typeInSignedJar)); + Object o = imposteriser.imposterise(new VoidAction(), typeInSignedJar); + + assertTrue(typeInSignedJar.isInstance(o)); + } } -- To stop receiving notification emails like this one, please contact ahu...@apache.org.