You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2016/01/29 23:00:10 UTC

tomee git commit: TOMEE-1701 SingleApplicationComposerRunner

Repository: tomee
Updated Branches:
  refs/heads/master cd1433e0e -> eb0c2da70


TOMEE-1701 SingleApplicationComposerRunner


Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/eb0c2da7
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/eb0c2da7
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/eb0c2da7

Branch: refs/heads/master
Commit: eb0c2da7015a191906e3507c677e39d3470e8d8a
Parents: cd1433e
Author: Romain Manni-Bucau <rm...@gmail.org>
Authored: Fri Jan 29 23:00:02 2016 +0100
Committer: Romain Manni-Bucau <rm...@gmail.org>
Committed: Fri Jan 29 23:00:02 2016 +0100

----------------------------------------------------------------------
 .../org/apache/openejb/testing/Application.java |  29 ++++
 .../SingleApplicationComposerRunner.java        | 171 +++++++++++++++++++
 2 files changed, 200 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tomee/blob/eb0c2da7/container/openejb-core/src/main/java/org/apache/openejb/testing/Application.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/testing/Application.java b/container/openejb-core/src/main/java/org/apache/openejb/testing/Application.java
new file mode 100644
index 0000000..568cbf4
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/testing/Application.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.openejb.testing;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Target({ FIELD, TYPE })
+@Retention(RUNTIME)
+public @interface Application {
+}

http://git-wip-us.apache.org/repos/asf/tomee/blob/eb0c2da7/container/openejb-core/src/main/java/org/apache/openejb/testing/SingleApplicationComposerRunner.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/testing/SingleApplicationComposerRunner.java b/container/openejb-core/src/main/java/org/apache/openejb/testing/SingleApplicationComposerRunner.java
new file mode 100644
index 0000000..1758ec6
--- /dev/null
+++ b/container/openejb-core/src/main/java/org/apache/openejb/testing/SingleApplicationComposerRunner.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.openejb.testing;
+
+import org.apache.openejb.core.ThreadContext;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.inject.OWBInjector;
+import org.apache.xbean.finder.AnnotationFinder;
+import org.apache.xbean.finder.archive.FileArchive;
+import org.junit.rules.MethodRule;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.apache.openejb.loader.JarLocation.jarLocation;
+
+// goal is to share the same container for all embedded tests and hold the config there
+// only works if all tests use the same config
+public class SingleApplicationComposerRunner extends BlockJUnit4ClassRunner {
+    private static volatile boolean started = false;
+    private static final AtomicReference<Object> APP = new AtomicReference<>();
+    private static final AtomicReference<Thread> HOOK = new AtomicReference<>();
+
+    public static void setApp(final Object o) {
+        APP.set(o);
+    }
+
+    public static void close() {
+        final Thread hook = HOOK.get();
+        if (hook != null) {
+            hook.run();
+            Runtime.getRuntime().removeShutdownHook(hook);
+            HOOK.compareAndSet(hook, null);
+            APP.set(null);
+        }
+    }
+
+    public SingleApplicationComposerRunner(final Class<?> klass) throws InitializationError {
+        super(klass);
+
+        if (APP.get() == null) {
+            final Class<?> type;
+            final String typeStr = System.getProperty("tomee.application-composer.application");
+            if (typeStr != null) {
+                try {
+                    type = Thread.currentThread().getContextClassLoader().loadClass(typeStr);
+                } catch (final ClassNotFoundException e) {
+                    throw new IllegalArgumentException(e);
+                }
+            } else {
+                final Iterator<Class<?>> descriptors =
+                    new AnnotationFinder(new FileArchive(Thread.currentThread().getContextClassLoader(), jarLocation(klass)), false)
+                        .findAnnotatedClasses(Application.class).iterator();
+                if (!descriptors.hasNext()) {
+                    throw new IllegalArgumentException("No descriptor class using @Application");
+                }
+                type = descriptors.next();
+                if (descriptors.hasNext()) {
+                    throw new IllegalArgumentException("Ambiguous @Application: " + type + ", " + descriptors.next());
+                }
+            }
+            try {
+                APP.compareAndSet(null, type.newInstance());
+            } catch (final InstantiationException | IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    @Override
+    protected List<MethodRule> rules(final Object test) {
+        final List<MethodRule> rules = super.rules(test);
+        rules.add(new MethodRule() {
+            @Override
+            public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+                return new Statement() {
+                    @Override
+                    public void evaluate() throws Throwable {
+                        start();
+                        OWBInjector.inject(WebBeansContext.currentInstance().getBeanManagerImpl(), target, null);
+                        composerInject(target);
+                        base.evaluate();
+                    }
+
+                    private void start() throws Exception {
+                        if (!started) {
+                            final Object app = APP.get();
+                            new ApplicationComposers(app.getClass()) {
+                                @Override
+                                public void deployApp(final Object inputTestInstance) throws Exception {
+                                    super.deployApp(inputTestInstance);
+                                    if (!started) {
+                                        final ThreadContext previous = ThreadContext.getThreadContext(); // done here for logging
+                                        final ApplicationComposers comp = this;
+                                        final Thread hook = new Thread() {
+                                            @Override
+                                            public void run() {
+                                                try {
+                                                    comp.after();
+                                                } catch (final Exception e) {
+                                                    ThreadContext.exit(previous);
+                                                    throw new IllegalStateException(e);
+                                                }
+                                            }
+                                        };
+                                        HOOK.set(hook);
+                                        Runtime.getRuntime().addShutdownHook(hook);
+                                        started = true;
+                                    }
+                                }
+                            }.before(app);
+                        }
+                    }
+                };
+            }
+        });
+        return rules;
+    }
+
+    private void composerInject(final Object target) throws IllegalAccessException {
+        final Object app = APP.get();
+        final Class<?> aClass = target.getClass();
+        for (final Field f : aClass.getDeclaredFields()) {
+            if (f.isAnnotationPresent(RandomPort.class)) {
+                for (final Field field : app.getClass().getDeclaredFields()) {
+                    if (field.getType() ==  f.getType()) {
+                        if (!field.isAccessible()) {
+                            field.setAccessible(true);
+                        }
+                        if (!f.isAccessible()) {
+                            f.setAccessible(true);
+                        }
+
+                        final Object value = field.get(app);
+                        f.set(target, value);
+                        break;
+                    }
+                }
+            } else if (f.isAnnotationPresent(Application.class)) {
+                if (!f.isAccessible()) {
+                    f.setAccessible(true);
+                }
+                f.set(target, app);
+            }
+        }
+        final Class<?> superclass = aClass.getSuperclass();
+        if (superclass != Object.class) {
+            composerInject(superclass);
+        }
+    }
+}