package com.arondor.common.reflection.noreflect.instantiator; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.logging.Level; import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.arondor.common.reflection.api.instantiator.InstantiationCallback; import com.arondor.common.reflection.api.instantiator.InstantiationContext; import com.arondor.common.reflection.api.instantiator.ReflectionInstantiator; import com.arondor.common.reflection.api.instantiator.ReflectionInstantiatorAsync; import com.arondor.common.reflection.api.parser.AccessibleClassParser; import com.arondor.common.reflection.bean.config.ObjectConfigurationFactoryBean; import com.arondor.common.reflection.bean.config.ObjectConfigurationMapBean; import com.arondor.common.reflection.model.config.ElementConfiguration; import com.arondor.common.reflection.model.config.ObjectConfiguration; import com.arondor.common.reflection.model.config.ObjectConfigurationFactory; import com.arondor.common.reflection.model.config.ObjectConfigurationMap; import com.arondor.common.reflection.model.java.AccessibleClass; import com.arondor.common.reflection.noreflect.generator.NoReflectRegistrarGenerator; import com.arondor.common.reflection.noreflect.model.AsyncPackages; import com.arondor.common.reflection.noreflect.model.ReflectionInstantiatorCatalog; import com.arondor.common.reflection.noreflect.model.ReflectionInstantiatorRegistrar; import com.arondor.common.reflection.noreflect.runtime.SimpleReflectionInstantiatorCatalog; import com.arondor.common.reflection.noreflect.testclasses.async.TestClass1; import com.arondor.common.reflection.noreflect.testclasses.async.submodule0.TestModule1Class1; import com.arondor.common.reflection.noreflect.testclasses.async.submodule0.TestModule1Class2; import com.arondor.common.reflection.noreflect.testclasses.async.submodule1.TestModule2Class1; import com.arondor.common.reflection.noreflect.testclasses.async.submodule1.TestModule2Class2; import com.arondor.common.reflection.parser.java.JavaAccessibleClassParser; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.thirdparty.guava.common.collect.Lists; public class TestAsyncInstantiator { private static final Logger LOG = Logger.getLogger(TestNoReflectRegistrarGenerator.class); protected InstantiationContext instantationContext; protected ReflectionInstantiator instantiator; protected ReflectionInstantiatorAsync asyncInstantiator; protected AccessibleClassParser parser; protected ObjectConfigurationFactory objectConfigurationFactory = new ObjectConfigurationFactoryBean(); private static long RUN_ASYNC_DELAY = 0; public static void junitRunAsync(final RunAsyncCallback callback) { new Thread() { @Override public void run() { if (RUN_ASYNC_DELAY > 0) { try { Thread.sleep(RUN_ASYNC_DELAY); } catch (InterruptedException e) { LOG.error("Could not wait", e); } } callback.onSuccess(); } }.start(); } private void doGenerate() throws FileNotFoundException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException { parser = new JavaAccessibleClassParser(); List<AccessibleClass> classes = new ArrayList<AccessibleClass>(); classes.add(parser.parseAccessibleClass(TestClass1.class)); AsyncPackages asyncPackages = new AsyncPackages(); asyncPackages.put( "module1", Lists.newArrayList(parser.parseAccessibleClass(TestModule1Class1.class), parser.parseAccessibleClass(TestModule1Class2.class))); asyncPackages.put( "module2", Lists.newArrayList(parser.parseAccessibleClass(TestModule2Class1.class), parser.parseAccessibleClass(TestModule2Class2.class))); NoReflectRegistrarGenerator gen = new NoReflectRegistrarGenerator(); gen.setAccessibleClassParser(parser); gen.setGwtRunAsyncMethod(TestAsyncInstantiator.class.getName() + ".junitRunAsync"); String packageName = "testing_"; String className = "AutoGen" + (int) (Math.random() * 10000); gen.setPackageName(packageName); gen.setClassName(className); // String path = "src/test/java/testing/" + .java"; new File("target/" + packageName).mkdir(); String path = "target/" + packageName + "/" + className + ".java"; String completeClassName = packageName + "." + className; OutputStream os = new FileOutputStream(path); PrintStream out = new PrintStream(os); gen.generate(out, classes, asyncPackages); out.close(); Class<?> clazz = runtimeCompileAndLoadClass(path, completeClassName); ReflectionInstantiatorRegistrar registrar = (ReflectionInstantiatorRegistrar) clazz.newInstance(); ReflectionInstantiatorCatalog catalog = new SimpleReflectionInstantiatorCatalog(); registrar.register(catalog); ReflectionInstantiatorNoReflect noReflect = new ReflectionInstantiatorNoReflect(); noReflect.setReflectionInstantiatorCatalog(catalog); this.instantiator = noReflect; this.asyncInstantiator = (ReflectionInstantiatorAsync) this.instantiator; this.instantationContext = noReflect.createDefaultInstantiationContext(); } private Class<?> runtimeCompileAndLoadClass(String path, String completeClassName) throws ClassNotFoundException { javax.tools.JavaCompiler javaCompiler = javax.tools.ToolProvider.getSystemJavaCompiler(); int result = javaCompiler.run(null, null, null, "-Xlint:unchecked", "-d", "target/classes/", path); LOG.info("Compile result : " + result); ClassLoader classLoader = javax.tools.ToolProvider.getSystemToolClassLoader(); Class<?> clazz = classLoader.loadClass(completeClassName); LOG.info("Loaded class : " + clazz.getName()); return clazz; } @Before public void setup() throws FileNotFoundException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException { // LogManager.getLogManager().getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME).setLevel(Level.FINEST); // LogManager.getLogManager().getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME) // .addHandler(new ConsoleLogHandler()); java.util.logging.Logger.getLogger(ReflectionInstantiatorNoReflect.class.getName()).setLevel(Level.FINEST); long start = System.currentTimeMillis(); doGenerate(); long end = System.currentTimeMillis(); LOG.info("setup() took " + (end - start) + "ms"); } @Test(timeout = 1000) public void testAsyncSingleton() throws InterruptedException { ObjectConfiguration root = objectConfigurationFactory.createObjectConfiguration(); root.setObjectName("Root"); root.setClassName(TestClass1.class.getName()); root.setSingleton(true); ObjectConfigurationMap objetConfigurations = new ObjectConfigurationMapBean(); objetConfigurations.put(root.getObjectName(), root); instantationContext.addSharedObjectConfigurations(objetConfigurations); asyncInstantiator.instanciateObject("Root", TestClass1.class, instantationContext, new InstantiationCallback<TestClass1>() { @Override public void onFailure(Throwable caught) { Assert.fail("Failed : " + caught); } @Override public void onSuccess(final TestClass1 result1) { Assert.assertNotNull(result1); asyncInstantiator.instanciateObject("Root", TestClass1.class, instantationContext, new InstantiationCallback<TestClass1>() { @Override public void onFailure(Throwable caught) { Assert.fail("Failed : " + caught); } @Override public void onSuccess(TestClass1 result2) { Assert.assertNotNull(result2); Assert.assertTrue("Diverging results !", result1 == result2); } }); } }); } @Test public void testAsyncNonSingleton() throws InterruptedException { ObjectConfiguration root = objectConfigurationFactory.createObjectConfiguration(); root.setObjectName("Root"); root.setClassName(TestClass1.class.getName()); root.setSingleton(false); ObjectConfigurationMap objetConfigurations = new ObjectConfigurationMapBean(); objetConfigurations.put(root.getObjectName(), root); instantationContext.addSharedObjectConfigurations(objetConfigurations); asyncInstantiator.instanciateObject("Root", TestClass1.class, instantationContext, new InstantiationCallback<TestClass1>() { @Override public void onFailure(Throwable caught) { Assert.fail("Failed : " + caught); } @Override public void onSuccess(final TestClass1 result1) { asyncInstantiator.instanciateObject("Root", TestClass1.class, instantationContext, new InstantiationCallback<TestClass1>() { @Override public void onFailure(Throwable caught) { Assert.fail("Failed : " + caught); } @Override public void onSuccess(TestClass1 result2) { Assert.assertTrue("Equal results !", result1 != result2); } }); } }); } @Test(timeout = 1000) public void testSimpleDependency() throws InterruptedException { ObjectConfiguration root = objectConfigurationFactory.createObjectConfiguration(); root.setObjectName("Root"); root.setClassName(TestClass1.class.getName()); root.setFields(new HashMap<String, ElementConfiguration>()); ObjectConfiguration child1 = objectConfigurationFactory.createObjectConfiguration(); child1.setClassName(TestModule1Class1.class.getName()); root.getFields().put("testModule1Class1", child1); final CountDownLatch latch = new CountDownLatch(1); asyncInstantiator.instanciateObject(root, Object.class, instantationContext, new InstantiationCallback<Object>() { @Override public void onFailure(Throwable caught) { Assert.fail("Failed : " + caught); } @Override public void onSuccess(Object result) { assertNotNull(result); assertTrue(result instanceof TestClass1); TestClass1 testClass1 = (TestClass1) result; assertNotNull(testClass1.getTestModule1Class1()); latch.countDown(); } }); latch.await(); } @Test(timeout = 1000) public void testDoubleDependency() throws InterruptedException { ObjectConfiguration root = objectConfigurationFactory.createObjectConfiguration(); root.setObjectName("Root"); root.setClassName(TestClass1.class.getName()); root.setFields(new HashMap<String, ElementConfiguration>()); ObjectConfiguration child1 = objectConfigurationFactory.createObjectConfiguration(); child1.setClassName(TestModule1Class1.class.getName()); root.getFields().put("testModule1Class1", child1); child1.setFields(new HashMap<String, ElementConfiguration>()); ObjectConfiguration grandChild1 = objectConfigurationFactory.createObjectConfiguration(); grandChild1.setClassName(TestModule2Class1.class.getName()); child1.getFields().put("testModule2Class1", grandChild1); final CountDownLatch latch = new CountDownLatch(1); asyncInstantiator.instanciateObject(root, Object.class, instantationContext, new InstantiationCallback<Object>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(Object result) { assertNotNull(result); assertTrue(result instanceof TestClass1); TestClass1 testClass1 = (TestClass1) result; assertNotNull(testClass1.getTestModule1Class1()); TestModule1Class1 testModule1Class1 = testClass1.getTestModule1Class1(); assertNotNull(testModule1Class1.getTestModule2Class1()); latch.countDown(); } }); latch.await(); } @Test // (timeout = 1000) public void testCyclicDependency() throws InterruptedException { ObjectConfiguration root = objectConfigurationFactory.createObjectConfiguration(); root.setObjectName("Root"); root.setClassName(TestClass1.class.getName()); root.setFields(new HashMap<String, ElementConfiguration>()); Map<String, ElementConfiguration> lastFields = root.getFields(); final int maxCycle = 200; for (int cycle = 0; cycle < maxCycle; cycle++) { ObjectConfiguration child1 = objectConfigurationFactory.createObjectConfiguration(); child1.setClassName(TestModule1Class1.class.getName()); child1.setFields(new HashMap<String, ElementConfiguration>()); lastFields.put("testModule1Class1", child1); ObjectConfiguration grandChild1 = objectConfigurationFactory.createObjectConfiguration(); grandChild1.setClassName(TestModule2Class1.class.getName()); grandChild1.setFields(new HashMap<String, ElementConfiguration>()); child1.getFields().put("testModule2Class1", grandChild1); lastFields = grandChild1.getFields(); } final CountDownLatch latch = new CountDownLatch(1); final long start = System.currentTimeMillis(); asyncInstantiator.instanciateObject(root, Object.class, instantationContext, new InstantiationCallback<Object>() { @Override public void onFailure(Throwable caught) { } @Override public void onSuccess(Object result) { final long end = System.currentTimeMillis(); LOG.info("Instantiation took :" + (end - start) + "ms"); assertNotNull(result); assertTrue(result instanceof TestClass1); TestClass1 testClass1 = (TestClass1) result; assertNotNull(testClass1.getTestModule1Class1()); TestModule1Class1 testModule1Class1 = testClass1.getTestModule1Class1(); for (int cycle = 0; cycle < maxCycle; cycle++) { TestModule2Class1 testModule2Class1 = testModule1Class1.getTestModule2Class1(); assertNotNull(testModule2Class1); assertNotSame(testModule1Class1, testModule2Class1.getTestModule1Class1()); testModule1Class1 = testModule2Class1.getTestModule1Class1(); if (cycle < maxCycle - 1) { assertNotNull(testModule1Class1); } else { assertNull(testModule1Class1); LOG.info("End of cycle:" + cycle); } } latch.countDown(); } }); latch.await(); } }