package org.kie.maven.plugin; import static org.junit.Assert.*; import java.io.File; import java.io.FilenameFilter; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; import org.drools.core.phreak.ReactiveObject; import org.junit.Test; import io.takari.maven.testing.executor.MavenExecutionResult; import io.takari.maven.testing.executor.MavenRuntime; public class InjectReactiveIntegrationTest extends KieMavenPluginBaseIntegrationTest { public InjectReactiveIntegrationTest(MavenRuntime.MavenRuntimeBuilder builder) throws Exception { super(builder); } @Test public void testBasicBytecodeInjection() throws Exception { File basedir = resources.getBasedir("kjar-4-bytecode-inject"); MavenExecutionResult result = mavenRuntime .forProject(basedir) .execute("clean", "install"); result.assertErrorFreeLog(); File classDir = new File(basedir, "target/classes"); System.out.println(classDir); List<URL> classloadingURLs = new ArrayList<>(); classloadingURLs.add(classDir.toURI().toURL()); classloadingURLs.add(new File(BytecodeInjectReactive.classpathFromClass(ReactiveObject.class)).toURI().toURL()); File libDir = new File(basedir, "target/lib"); for (File jar : libDir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jar"); } })) { classloadingURLs.add(jar.toURI().toURL()); } ClassLoader cl = new URLClassLoader( classloadingURLs.toArray(new URL[]{}), null ); assertTrue( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.Adult") ) ); assertTrue( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.UsingADependencyClass") ) ); assertTrue( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.UsingSpecializedList") ) ); assertTrue( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.TMFile") ) ); assertTrue( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.TMFileSet") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.ImmutablePojo") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.FieldIsNotListInterface") ) ); } @Test public void testBasicBytecodeInjectionSelected() throws Exception { File basedir = resources.getBasedir("kjar-5-bytecode-inject-selected"); MavenExecutionResult result = mavenRuntime .forProject(basedir) .execute("clean", "install"); result.assertErrorFreeLog(); File classDir = new File(basedir, "target/classes"); System.out.println(classDir); List<URL> classloadingURLs = new ArrayList<>(); classloadingURLs.add(classDir.toURI().toURL()); classloadingURLs.add(new File(BytecodeInjectReactive.classpathFromClass(ReactiveObject.class)).toURI().toURL()); File libDir = new File(basedir, "target/lib"); for (File jar : libDir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jar"); } })) { classloadingURLs.add(jar.toURI().toURL()); } ClassLoader cl = new URLClassLoader( classloadingURLs.toArray(new URL[]{}), null ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.Adult") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.UsingADependencyClass") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.UsingSpecializedList") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.TMFile") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.TMFileSet") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("org.drools.compiler.xpath.tobeinstrumented.model.ImmutablePojo") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("to.instrument.Adult") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("to.instrument.UsingADependencyClass") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("to.instrument.UsingSpecializedList") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("to.instrument.TMFile") ) ); assertTrue ( looksLikeInstrumentedClass( cl.loadClass("to.instrument.TMFileSet") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.instrument.ImmutablePojo") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.Adult") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.UsingADependencyClass") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.UsingSpecializedList") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.TMFile") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.TMFileSet") ) ); assertFalse( looksLikeInstrumentedClass( cl.loadClass("to.not.instrument.ImmutablePojo") ) ); } private boolean looksLikeInstrumentedClass(Class<?> personClass) { boolean foundReactiveObjectInterface = false; for ( Class<?> i : personClass.getInterfaces() ){ if ( i.getName().equals(ReactiveObject.class.getName()) ) { foundReactiveObjectInterface = true; } } // the ReactiveObject interface method are injected by the bytecode instrumenter, better check they are indeed available.. boolean containsGetLeftTuple = checkContainsMethod(personClass, "getLeftTuples"); boolean containsAddLeftTuple = checkContainsMethod(personClass, "addLeftTuple"); boolean containsRemoveLeftTuple = checkContainsMethod(personClass, "removeLeftTuple"); boolean foundReactiveInjectedMethods = false; for ( Method m : personClass.getMethods() ){ if ( m.getName().startsWith(BytecodeInjectReactive.DROOLS_PREFIX) ) { foundReactiveInjectedMethods = true; } } return foundReactiveObjectInterface && containsGetLeftTuple && containsAddLeftTuple && containsRemoveLeftTuple && foundReactiveInjectedMethods ; } private boolean checkContainsMethod(Class<?> personClass, Object methodName) { for ( Method m : personClass.getMethods() ){ if (m.getName().equals(methodName)) { return true; } } return false; } }