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);
+ }
+ }
+}