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 2015/02/22 22:13:23 UTC
tomee git commit: TOMEE-1518 ContainerRule and ApplicationRule
Repository: tomee
Updated Branches:
refs/heads/develop e79c813e2 -> 7ab0188cd
TOMEE-1518 ContainerRule and ApplicationRule
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo
Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/7ab0188c
Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/7ab0188c
Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/7ab0188c
Branch: refs/heads/develop
Commit: 7ab0188cd06c4b74ce9079299d4a58c76f18ac24
Parents: e79c813
Author: Romain Manni-Bucau <rm...@apache.org>
Authored: Sun Feb 22 22:13:11 2015 +0100
Committer: Romain Manni-Bucau <rm...@apache.org>
Committed: Sun Feb 22 22:13:11 2015 +0100
----------------------------------------------------------------------
.../openejb/junit/ApplicationComposerRule.java | 8 +
.../openejb/testing/ApplicationComposers.java | 750 ++++++++++---------
.../org/apache/openejb/testing/Classes.java | 2 +
.../org/apache/openejb/util/StringTemplate.java | 2 +-
4 files changed, 407 insertions(+), 355 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tomee/blob/7ab0188c/container/openejb-core/src/main/java/org/apache/openejb/junit/ApplicationComposerRule.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/junit/ApplicationComposerRule.java b/container/openejb-core/src/main/java/org/apache/openejb/junit/ApplicationComposerRule.java
index b804a8e..79207ec 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/junit/ApplicationComposerRule.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/junit/ApplicationComposerRule.java
@@ -35,6 +35,14 @@ public class ApplicationComposerRule implements TestRule {
}
}
+ public <T> T getInstance(final Class<T> as) {
+ return as.cast(instance);
+ }
+
+ public Object[] getModules() {
+ return modules;
+ }
+
@Override
public Statement apply(final Statement base, final Description description) {
return new DeployApplication(instance, base, new ApplicationComposers(instance.getClass(), modules));
http://git-wip-us.apache.org/repos/asf/tomee/blob/7ab0188c/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
index 20d24fc..108dd26 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java
@@ -90,7 +90,10 @@ import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClassesArchive;
import org.apache.xbean.finder.archive.CompositeArchive;
import org.apache.xbean.finder.archive.FileArchive;
+import org.apache.xbean.finder.archive.FilteredArchive;
import org.apache.xbean.finder.archive.JarArchive;
+import org.apache.xbean.finder.filter.Filter;
+import org.apache.xbean.finder.filter.Filters;
import org.xml.sax.InputSource;
import java.io.File;
@@ -123,14 +126,16 @@ import javax.enterprise.inject.spi.Extension;
import javax.inject.Inject;
import javax.naming.Context;
import javax.naming.InitialContext;
+import javax.naming.NamingException;
import static java.util.Arrays.asList;
import static org.apache.openejb.config.DeploymentFilterable.DEPLOYMENTS_CLASSPATH_PROPERTY;
import static org.apache.openejb.loader.JarLocation.jarLocation;
import static org.apache.openejb.util.Classes.ancestors;
+// TODO: surely explode it and base it on refactored ContainerRule and DeployApplicationRule
@SuppressWarnings("deprecation")
-public final class ApplicationComposers {
+public class ApplicationComposers {
public static final String OPENEJB_APPLICATION_COMPOSER_CONTEXT = "openejb.application.composer.context";
private static final Class[] MODULE_TYPES = {IAnnotationFinder.class, ClassesArchive.class,
@@ -147,7 +152,7 @@ public final class ApplicationComposers {
}
private final Map<Object, ClassFinder> testClassFinders;
- private final Class<?> testClass;
+ private Class<?> testClass;
private ServiceManagerProxy serviceManager;
// invocation context
@@ -177,89 +182,99 @@ public final class ApplicationComposers {
}
validate();
+ assembler = SystemInstance.get().getComponent(Assembler.class); // for DeployApplicationRule we need it
+ }
+
+ protected boolean isContainer() {
+ return true;
+ }
+
+ protected boolean isApplication() {
+ return true;
}
private void validate() {
final List<Throwable> errors = new ArrayList<>();
- final Map<Object, List<Method>> annotatedConfigurationMethods = findAnnotatedMethods(new HashMap<Object, List<Method>>(), Configuration.class);
- {
- int nbProp = 0;
- int nbOpenejb = 0;
- for (final List<Method> list : annotatedConfigurationMethods.values()) {
- for (final Method m : list) {
- final Class<?> type = m.getReturnType();
- if (Openejb.class.isAssignableFrom(type) || String.class.equals(type)) {
- nbOpenejb++;
- } else if (Properties.class.isAssignableFrom(type)) {
- nbProp++;
- } // else not supported?
+ if (isContainer()) {
+ final Map<Object, List<Method>> annotatedConfigurationMethods = findAnnotatedMethods(new HashMap<Object, List<Method>>(), Configuration.class);
+ {
+ int nbProp = 0;
+ int nbOpenejb = 0;
+ for (final List<Method> list : annotatedConfigurationMethods.values()) {
+ for (final Method m : list) {
+ final Class<?> type = m.getReturnType();
+ if (Openejb.class.isAssignableFrom(type) || String.class.equals(type)) {
+ nbOpenejb++;
+ } else if (Properties.class.isAssignableFrom(type)) {
+ nbProp++;
+ } // else not supported?
+ }
+ }
+ if (nbProp > 1 || nbOpenejb > 1) {
+ final String gripe = "Test class should have no more than one @Configuration method by type (Openejb/String or Properties)";
+ errors.add(new Exception(gripe));
}
}
- if (nbProp > 1 || nbOpenejb > 1) {
- final String gripe = "Test class should have no more than one @Configuration method by type (Openejb/String or Properties)";
- errors.add(new Exception(gripe));
- }
- }
-
- int injectorSize = 0;
- for (final List<Method> m : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.MockInjector.class).values()) {
- injectorSize += m.size();
- }
- for (final List<Method> m : findAnnotatedMethods(new HashMap<Object, List<Method>>(), MockInjector.class).values()) {
- injectorSize += m.size();
- }
- if (injectorSize > 1) {
- errors.add(new Exception("Test class should have no more than one @MockInjector method"));
- }
- final List<Method> components = new ArrayList<>();
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Component.class).values()) {
- components.addAll(l);
- }
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Component.class).values()) {
- components.addAll(l);
- }
- for (final Method method : components) {
- if (method.getParameterTypes().length > 0) {
- errors.add(new Exception("@Component methods shouldn't take any parameters"));
+ int injectorSize = 0;
+ for (final List<Method> m : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.MockInjector.class).values()) {
+ injectorSize += m.size();
+ }
+ for (final List<Method> m : findAnnotatedMethods(new HashMap<Object, List<Method>>(), MockInjector.class).values()) {
+ injectorSize += m.size();
+ }
+ if (injectorSize > 1) {
+ errors.add(new Exception("Test class should have no more than one @MockInjector method"));
}
- }
- final List<Method> descriptors = new ArrayList<>();
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Descriptors.class).values()) {
- descriptors.addAll(l);
- }
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Descriptors.class).values()) {
- descriptors.addAll(l);
- }
- for (final Method method : descriptors) {
- final Class<?> returnType = method.getReturnType();
- if (!returnType.equals(WebModule.class) && !returnType.equals(EjbModule.class)
- && !returnType.equals(WebApp.class) && !returnType.equals(EjbJar.class)
- && !returnType.equals(AppModule.class)) {
- errors.add(new Exception("@Descriptors can't be used on " + returnType.getName()));
+ final List<Method> components = new ArrayList<>();
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Component.class).values()) {
+ components.addAll(l);
+ }
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Component.class).values()) {
+ components.addAll(l);
+ }
+ for (final Method method : components) {
+ if (method.getParameterTypes().length > 0) {
+ errors.add(new Exception("@Component methods shouldn't take any parameters"));
+ }
+ }
+ for (final ClassFinder finder : testClassFinders.values()) {
+ for (final Field field : finder.findAnnotatedFields(RandomPort.class)) {
+ final Class<?> type = field.getType();
+ if (int.class != type && URL.class != type) {
+ throw new IllegalArgumentException("@RandomPort is only supported for int fields");
+ }
+ }
}
}
- final List<Method> classes = new ArrayList<>();
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Classes.class).values()) {
- classes.addAll(l);
- }
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Classes.class).values()) {
- classes.addAll(l);
- }
- for (final Method method : classes) {
- final Class<?> returnType = method.getReturnType();
- if (!returnType.equals(WebModule.class) && !returnType.equals(EjbModule.class)
- && !returnType.equals(WebApp.class) && !returnType.equals(EjbJar.class)
- && !EnterpriseBean.class.isAssignableFrom(returnType)) {
- errors.add(new Exception("@Classes can't be used on a method returning " + returnType));
+ if (isApplication()) {
+ final List<Method> descriptors = new ArrayList<>();
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Descriptors.class).values()) {
+ descriptors.addAll(l);
+ }
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Descriptors.class).values()) {
+ descriptors.addAll(l);
+ }
+ for (final Method method : descriptors) {
+ final Class<?> returnType = method.getReturnType();
+ if (!returnType.equals(WebModule.class) && !returnType.equals(EjbModule.class)
+ && !returnType.equals(WebApp.class) && !returnType.equals(EjbJar.class)
+ && !returnType.equals(AppModule.class)) {
+ errors.add(new Exception("@Descriptors can't be used on " + returnType.getName()));
+ }
}
- }
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Jars.class).values()) {
- for (final Method method : l) {
+ final List<Method> classes = new ArrayList<>();
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Classes.class).values()) {
+ classes.addAll(l);
+ }
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Classes.class).values()) {
+ classes.addAll(l);
+ }
+ for (final Method method : classes) {
final Class<?> returnType = method.getReturnType();
if (!returnType.equals(WebModule.class) && !returnType.equals(EjbModule.class)
&& !returnType.equals(WebApp.class) && !returnType.equals(EjbJar.class)
@@ -267,51 +282,52 @@ public final class ApplicationComposers {
errors.add(new Exception("@Classes can't be used on a method returning " + returnType));
}
}
- }
- int appModules = 0;
- int modules = 0;
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Jars.class).values()) {
+ for (final Method method : l) {
+ final Class<?> returnType = method.getReturnType();
+ if (!returnType.equals(WebModule.class) && !returnType.equals(EjbModule.class)
+ && !returnType.equals(WebApp.class) && !returnType.equals(EjbJar.class)
+ && !EnterpriseBean.class.isAssignableFrom(returnType)) {
+ errors.add(new Exception("@Classes can't be used on a method returning " + returnType));
+ }
+ }
+ }
- final List<Method> moduleMethods = new ArrayList<>();
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Module.class).values()) {
- moduleMethods.addAll(l);
- }
- for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Module.class).values()) {
- moduleMethods.addAll(l);
- }
- for (final Method method : moduleMethods) {
+ int appModules = 0;
+ int modules = 0;
- modules++;
+ final List<Method> moduleMethods = new ArrayList<>();
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Module.class).values()) {
+ moduleMethods.addAll(l);
+ }
+ for (final List<Method> l : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Module.class).values()) {
+ moduleMethods.addAll(l);
+ }
+ for (final Method method : moduleMethods) {
- final Class<?> type = method.getReturnType();
+ modules++;
- if (Application.class.isAssignableFrom(type)) {
+ final Class<?> type = method.getReturnType();
- appModules++;
+ if (Application.class.isAssignableFrom(type)) {
- } else if (!isValidModuleType(type, MODULE_TYPES)) {
- final String gripe = "@Module method must return " + Join.join(" or ", MODULE_TYPES).replaceAll("(class|interface) ", "");
- errors.add(new Exception(gripe));
- }
- }
-
- for (final ClassFinder finder : testClassFinders.values()) {
- for (final Field field : finder.findAnnotatedFields(RandomPort.class)) {
- final Class<?> type = field.getType();
- if (int.class != type && URL.class != type) {
- throw new IllegalArgumentException("@RandomPort is only supported for int fields");
+ appModules++;
+ } else if (!isValidModuleType(type, MODULE_TYPES)) {
+ final String gripe = "@Module method must return " + Join.join(" or ", MODULE_TYPES).replaceAll("(class|interface) ", "");
+ errors.add(new Exception(gripe));
}
}
- }
- if (appModules > 1) {
- final String gripe = "Test class should have no more than one @Module method that returns " + Application.class.getName();
- errors.add(new Exception(gripe));
- }
+ if (appModules > 1) {
+ final String gripe = "Test class should have no more than one @Module method that returns " + Application.class.getName();
+ errors.add(new Exception(gripe));
+ }
- if (modules < 1 && testClass.getAnnotation(Classes.class) == null && testClass.getAnnotation(Default.class) == null) {
- final String gripe = "Test class should have at least one @Module method";
- errors.add(new Exception(gripe));
+ if (modules < 1 && testClass.getAnnotation(Classes.class) == null && testClass.getAnnotation(Default.class) == null) {
+ final String gripe = "Test class should have at least one @Module method";
+ errors.add(new Exception(gripe));
+ }
}
if (!errors.isEmpty()) {
@@ -348,6 +364,15 @@ public final class ApplicationComposers {
// we hacked testInstance while we were not aware of it, now we can solve it
testClassFinders.put(inputTestInstance, testClassFinders.remove(this));
+ startContainer(inputTestInstance);
+
+ servletContext = new MockServletContext();
+ session = new MockHttpSession();
+
+ deployApp(inputTestInstance);
+ }
+
+ public void deployApp(final Object inputTestInstance) throws Exception {
final ClassLoader loader = testClass.getClassLoader();
AppModule appModule = new AppModule(loader, testClass.getSimpleName());
@@ -373,154 +398,6 @@ public final class ApplicationComposers {
appModule.getEjbModules().add(ejbModule);
}
- // For the moment we just take the first @Configuration method
- // maybe later we can add something fancy to allow multiple configurations using a qualifier
- // as a sort of altDD/altConfig concept. Say for example the altDD prefix might be "foo",
- // we can then imagine something like this:
- // @Foo @Configuration public Properties alternateConfig(){...}
- // @Foo @Module public Properties alternateModule(){...}
- // anyway, one thing at a time ....
-
- final Properties configuration = new Properties();
- configuration.put(DEPLOYMENTS_CLASSPATH_PROPERTY, "false");
-
- final EnableServices annotation = testClass.getAnnotation(EnableServices.class);
- if (annotation != null && annotation.httpDebug()) {
- configuration.setProperty("httpejbd.print", "true");
- configuration.setProperty("httpejbd.indent.xml", "true");
- configuration.setProperty("logging.level.OpenEJB.server.http", "FINE");
- }
- final org.apache.openejb.junit.EnableServices annotationOld = testClass.getAnnotation(org.apache.openejb.junit.EnableServices.class);
- if (annotationOld != null && annotationOld.httpDebug()) {
- configuration.setProperty("httpejbd.print", "true");
- configuration.setProperty("httpejbd.indent.xml", "true");
- configuration.setProperty("logging.level.OpenEJB.server.http", "FINE");
- }
- final WebResource webResource = testClass.getAnnotation(WebResource.class);
- if (webResource != null && webResource.value().length > 0) {
- configuration.setProperty("openejb.embedded.http.resources", Join.join(",", webResource.value()));
- }
-
- Openejb openejb = null;
- final Map<Object, List<Method>> configs = new HashMap<>();
- findAnnotatedMethods(configs, Configuration.class);
- findAnnotatedMethods(configs, org.apache.openejb.junit.Configuration.class);
- for (final Map.Entry<Object, List<Method>> method : configs.entrySet()) {
- for (final Method m : method.getValue()) {
- final Object o = m.invoke(method.getKey());
- if (o instanceof Properties) {
- final Properties properties = (Properties) o;
- configuration.putAll(properties);
- } else if (Openejb.class.isInstance(o)) {
- openejb = Openejb.class.cast(o);
- } else if (String.class.isInstance(o)) {
- final String path = String.class.cast(o);
- final URL url = Thread.currentThread().getContextClassLoader().getResource(path);
- if (url == null) {
- throw new IllegalArgumentException(o.toString() + " not found");
- }
- final InputStream in = url.openStream();
- try {
- if (path.endsWith(".json")) {
- openejb = JSonConfigReader.read(Openejb.class, in);
- } else {
- openejb = JaxbOpenejb.readConfig(new InputSource(in));
- }
- } finally {
- IO.close(in);
- }
- }
- }
- }
-
- if (SystemInstance.isInitialized()) {
- SystemInstance.reset();
- }
-
- Collection<String> propertiesToSetAgain = null;
- final ContainerProperties configAnnot = testClass.getAnnotation(ContainerProperties.class);
- if (configAnnot != null) {
- for (final ContainerProperties.Property p : configAnnot.value()) {
- final String value = p.value();
- final String name = p.name();
- configuration.put(name, value.equals(ContainerProperties.Property.IGNORED) ? null : value);
- if (value.contains("${")) {
- if (propertiesToSetAgain == null) {
- propertiesToSetAgain = new LinkedList<>();
- }
- propertiesToSetAgain.add(name);
- }
- }
- }
-
- SystemInstance.init(configuration);
- for (final Map.Entry<Object, ClassFinder> finder : testClassFinders.entrySet()) {
- for (final Field field : finder.getValue().findAnnotatedFields(RandomPort.class)) {
- if (!field.isAccessible()) {
- field.setAccessible(true);
- }
-
- final String service = field.getAnnotation(RandomPort.class).value();
- final String key = ("http".equals(service) ? "httpejbd" : service) + ".port";
- final String existing = SystemInstance.get().getProperty(key);
- final int random;
- if (existing == null) {
- random = NetworkUtil.getNextAvailablePort();
- SystemInstance.get().setProperty(key, Integer.toString(random));
- } else {
- random = Integer.parseInt(existing);
- }
- if (int.class == field.getType()) {
- field.set(finder.getKey(), random);
- } else if (URL.class == field.getType()) {
- field.set(finder.getKey(), new URL("http://localhost:" + random + "/"));
- }
- }
- }
-
- for (final Map.Entry<Object, ClassFinder> finder : testClassFinders.entrySet()) {
- if (!finder.getValue().findAnnotatedClasses(SimpleLog.class).isEmpty()) {
- SystemInstance.get().setProperty("openejb.jul.forceReload", "true");
- break;
- }
- }
-
- final CdiExtensions cdiExtensions = testClass.getAnnotation(CdiExtensions.class);
- if (cdiExtensions != null) {
- SystemInstance.get().setComponent(LoaderService.class, new ExtensionAwareOptimizedLoaderService(cdiExtensions.value()));
- }
-
- // save the test under test to be able to retrieve it from extensions
- // /!\ has to be done before all other init
- SystemInstance.get().setComponent(TestInstance.class, new TestInstance(testClass, inputTestInstance));
-
- // call the mock injector before module method to be able to use mocked classes
- // it will often use the TestInstance so
- final Map<Object, List<Method>> mockInjectors = new HashMap<>();
- findAnnotatedMethods(mockInjectors, MockInjector.class);
- findAnnotatedMethods(mockInjectors, org.apache.openejb.junit.MockInjector.class);
- if (!mockInjectors.isEmpty() && !mockInjectors.values().iterator().next().isEmpty()) {
- final Map.Entry<Object, List<Method>> methods = mockInjectors.entrySet().iterator().next();
- Object o = methods.getValue().iterator().next().invoke(methods.getKey());
- if (o instanceof Class<?>) {
- o = ((Class<?>) o).newInstance();
- }
- if (o instanceof FallbackPropertyInjector) {
- SystemInstance.get().setComponent(FallbackPropertyInjector.class, (FallbackPropertyInjector) o);
- }
- }
-
- for (final Map.Entry<Object, List<Method>> method : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Component.class).entrySet()) {
- for (final Method m : method.getValue()) {
- setComponent(method.getKey(), m);
- }
- }
- for (final Map.Entry<Object, List<Method>> method : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Component.class).entrySet()) {
- for (final Method m : method.getValue()) {
- setComponent(method.getKey(), m);
- }
- }
-
final Map<String, URL> additionalDescriptors = descriptorsToMap(testClass.getAnnotation(org.apache.openejb.junit.Descriptors.class));
final Map<String, URL> additionalDescriptorsNew = descriptorsToMap(testClass.getAnnotation(Descriptors.class));
additionalDescriptors.putAll(additionalDescriptorsNew);
@@ -544,6 +421,7 @@ public final class ApplicationComposers {
final boolean defaultConfig = method.getAnnotation(Default.class) != null;
Class<?>[] classes = null;
+ String[] excludes = null;
Class<?>[] cdiInterceptors = null;
Class<?>[] cdiAlternatives = null;
Class<?>[] cdiDecorators = null;
@@ -551,6 +429,7 @@ public final class ApplicationComposers {
boolean innerClassesAsBean = false;
if (classesAnnotation != null) {
classes = classesAnnotation.value();
+ excludes = classesAnnotation.excludes();
innerClassesAsBean = classesAnnotation.innerClassesAsBean();
cdiInterceptors = classesAnnotation.cdiInterceptors();
cdiDecorators = classesAnnotation.cdiDecorators();
@@ -572,7 +451,7 @@ public final class ApplicationComposers {
method.getAnnotation(Descriptors.class), method.getAnnotation(JaxrsProviders.class),
webApp,
globalJarsAnnotation, jarsAnnotation,
- classes, cdiInterceptors, cdiAlternatives, cdiDecorators, cdi, innerClassesAsBean,
+ classes, excludes, cdiInterceptors, cdiAlternatives, cdiDecorators, cdi, innerClassesAsBean,
defaultConfig);
} else if (obj instanceof WebModule) { // will add the ejbmodule too
webModulesNb++;
@@ -592,7 +471,7 @@ public final class ApplicationComposers {
if (defaultConfig) {
(files == null ? files = new LinkedList<>() : files).add(jarLocation(testClass));
}
- webModule.setFinder(finderFromClasses(webModule, classes, files));
+ webModule.setFinder(finderFromClasses(webModule, classes, files, excludes));
ejbModule.setFinder(webModule.getFinder());
} else if (obj instanceof EjbModule) {
final EjbModule ejbModule = (EjbModule) obj;
@@ -610,7 +489,7 @@ public final class ApplicationComposers {
if (defaultConfig) {
(files == null ? files = new LinkedList<>() : files).add(jarLocation(testClass));
}
- ejbModule.setFinder(finderFromClasses(ejbModule, classes, files));
+ ejbModule.setFinder(finderFromClasses(ejbModule, classes, files, excludes));
} else if (obj instanceof EjbJar) {
final EjbJar ejbJar = (EjbJar) obj;
@@ -630,7 +509,7 @@ public final class ApplicationComposers {
if (defaultConfig) {
(files == null ? files = new LinkedList<>() : files).add(jarLocation(testClass));
}
- ejbModule.setFinder(finderFromClasses(ejbModule, classes, files));
+ ejbModule.setFinder(finderFromClasses(ejbModule, classes, files, excludes));
} else if (obj instanceof EnterpriseBean) {
final EnterpriseBean bean = (EnterpriseBean) obj;
@@ -648,7 +527,7 @@ public final class ApplicationComposers {
if (defaultConfig) {
(files == null ? files = new LinkedList<>() : files).add(jarLocation(testClass));
}
- ejbModule.setFinder(finderFromClasses(ejbModule, classes, files));
+ ejbModule.setFinder(finderFromClasses(ejbModule, classes, files, excludes));
} else if (obj instanceof Application) {
application = (Application) obj;
@@ -683,7 +562,7 @@ public final class ApplicationComposers {
if (defaultConfig) {
(files == null ? files = new LinkedList<>() : files).add(jarLocation(testClass));
}
- ejbModule.setFinder(finderFromClasses(ejbModule, classes, files));
+ ejbModule.setFinder(finderFromClasses(ejbModule, classes, files, excludes));
} else if (obj instanceof Class[]) {
final Class[] beans = (Class[]) obj;
@@ -743,7 +622,7 @@ public final class ApplicationComposers {
addWebApp(
appModule, testBean, additionalDescriptors,
null, null,
- webapp, globalJarsAnnotation, null, classClasses.value(),
+ webapp, globalJarsAnnotation, null, classClasses.value(), classClasses.excludes(),
classClasses.cdiInterceptors(), classClasses.cdiAlternatives(), classClasses.cdiDecorators(),
classClasses.cdi(), classClasses.innerClassesAsBean(), testClass.getAnnotation(Default.class) != null);
webModulesNb++;
@@ -791,66 +670,15 @@ public final class ApplicationComposers {
}
}
- if (webModulesNb > 0 && SystemInstance.get().getComponent(WebAppBuilder.class) == null) {
- SystemInstance.get().setComponent(WebAppBuilder.class, new LightweightWebAppBuilder());
- }
-
if (moduleMethods.size() == 1 && webModulesNb == 1) {
appModule.setStandloneWebModule();
}
- final ConfigurationFactory config = new ConfigurationFactory();
- config.init(SystemInstance.get().getProperties());
-
- assembler = new Assembler();
- SystemInstance.get().setComponent(Assembler.class, assembler);
-
- final OpenEjbConfiguration openEjbConfiguration;
- if (openejb != null) {
- openEjbConfiguration = config.getOpenEjbConfiguration(openejb);
- } else {
- openEjbConfiguration = config.getOpenEjbConfiguration();
- }
- assembler.buildContainerSystem(openEjbConfiguration);
-
- if ("true".equals(configuration.getProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "false"))
- || annotation != null || annotationOld != null) {
- try {
- if (annotation != null) {
- final List<String> value = new ArrayList<String>(asList(annotation.value()));
- if (annotation.jaxrs()) {
- value.add("jaxrs");
- }
- if (annotation.jaxws()) {
- value.add("jaxws");
- }
- initFilteredServiceManager(value.toArray(new String[value.size()]));
- }
- if (annotationOld != null) {
- initFilteredServiceManager(annotationOld.value());
- }
- serviceManager = new ServiceManagerProxy(false);
- serviceManager.start();
- } catch (final ServiceManagerProxy.AlreadyStartedException e) {
- throw new OpenEJBRuntimeException(e);
- }
- }
-
- if (propertiesToSetAgain != null) {
- for (final String name : propertiesToSetAgain) {
- final String value = PropertyPlaceHolderHelper.simpleValue(SystemInstance.get().getProperty(name));
- configuration.put(name, value);
- System.setProperty(name, value); // done lazily to support placeholders so container will not do it here
- }
- propertiesToSetAgain.clear();
+ if (webModulesNb > 0 && SystemInstance.get().getComponent(WebAppBuilder.class) == null) {
+ SystemInstance.get().setComponent(WebAppBuilder.class, new LightweightWebAppBuilder());
}
- servletContext = new MockServletContext();
- session = new MockHttpSession();
-
- final ContainerSystem containerSystem = SystemInstance.get().getComponent(ContainerSystem.class);
- final Context jndiContext = containerSystem.getJNDIContext();
-
+ final Context jndiContext = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
for (final EnvEntry entry : testBean.getEnvEntry()) { // set it in global jndi context since that's "app" entries and otherwise when we are no more in test bean context lookup fails
final String name = entry.getName();
final String jndi;
@@ -862,15 +690,14 @@ public final class ApplicationComposers {
jndiContext.bind(jndi, entry.getEnvEntryValue());
}
- appInfo = config.configureApplication(appModule);
-
+ appInfo = SystemInstance.get().getComponent(ConfigurationFactory.class).configureApplication(appModule);
appContext = assembler.createApplication(appInfo);
if (mockCdiContexts()) {
ScopeHelper.startContexts(appContext.getWebBeansContext().getContextsService(), servletContext, session);
}
- final BeanContext context = containerSystem.getBeanContext(testClass.getName());
+ final BeanContext context = SystemInstance.get().getComponent(ContainerSystem.class).getBeanContext(testClass.getName());
enrich(inputTestInstance, context);
@@ -915,7 +742,7 @@ public final class ApplicationComposers {
testClassFinders.put(this, testClassFinder);
}
- private boolean mockCdiContexts() {
+ protected boolean mockCdiContexts() {
return "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.testing.start-cdi-contexts", "true"));
}
@@ -926,6 +753,7 @@ public final class ApplicationComposers {
final WebApp webapp, final Jars globalJarsAnnotation,
final Jars jarsAnnotation,
final Class<?>[] cdiClasses,
+ final String[] excludes,
final Class<?>[] cdiInterceptors,
final Class<?>[] cdiAlternatives,
final Class<?>[] cdiDecorators,
@@ -1023,7 +851,7 @@ public final class ApplicationComposers {
}
}
- final IAnnotationFinder finder = finderFromClasses(webModule, classes, libs);
+ final IAnnotationFinder finder = finderFromClasses(webModule, classes, libs, excludes);
webModule.setFinder(finder);
ejbModule.setFinder(webModule.getFinder());
if (providersClasses != null) {
@@ -1042,6 +870,10 @@ public final class ApplicationComposers {
}
private void enrich(final Object inputTestInstance, final BeanContext context) throws org.apache.openejb.OpenEJBException {
+ if (context == null) {
+ return;
+ }
+
final ThreadContext callContext = new ThreadContext(context, null, Operation.INJECTION);
final ThreadContext oldContext = ThreadContext.enter(callContext);
try {
@@ -1163,40 +995,10 @@ public final class ApplicationComposers {
try {
runAll(beforeDestroyAfterRunnables);
if (assembler != null) {
- final ContextsService contextsService = appContext.getWebBeansContext().getContextsService();
- contextsService.endContext(SessionScoped.class, session);
- contextsService.endContext(RequestScoped.class, null);
- contextsService.endContext(ConversationScoped.class, null);
-
- try {
- assembler.destroyApplication(appInfo.path);
- } catch (final Exception e) {
- // no-op
- }
-
- final ContainerSystem component = SystemInstance.get().getComponent(ContainerSystem.class);
-
- if (null != component) {
- final Context context = component.getJNDIContext();
-
- for (final String entry : globalJndiEntries) {
- context.unbind(entry);
- }
- }
-
- globalJndiEntries.clear();
-
- if (mockCdiContexts()) {
- try {
- ScopeHelper.stopContexts(contextsService, servletContext, session);
- } catch (final Exception e) {
- // no-op
- }
- }
+ stopApplication();
}
if (serviceManager != null) {
-
try {
serviceManager.stop();
} catch (final RuntimeException ignored) {
@@ -1210,6 +1012,43 @@ public final class ApplicationComposers {
}
}
+ public void stopApplication() throws NamingException {
+ if (appContext != null) {
+ final ContextsService contextsService = appContext.getWebBeansContext().getContextsService();
+ contextsService.endContext(SessionScoped.class, session);
+ contextsService.endContext(RequestScoped.class, null);
+ contextsService.endContext(ConversationScoped.class, null);
+ }
+
+ if (appInfo != null) {
+ try {
+ assembler.destroyApplication(appInfo.path);
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+
+ final ContainerSystem component = SystemInstance.get().getComponent(ContainerSystem.class);
+
+ if (null != component) {
+ final Context context = component.getJNDIContext();
+
+ for (final String entry : globalJndiEntries) {
+ context.unbind(entry);
+ }
+ }
+
+ globalJndiEntries.clear();
+
+ if (mockCdiContexts() && appContext != null) {
+ try {
+ ScopeHelper.stopContexts(appContext.getWebBeansContext().getContextsService(), servletContext, session);
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+ }
+
private void runAll(final Collection<Runnable> runnables) {
for (final Runnable r : runnables) {
try {
@@ -1285,23 +1124,27 @@ public final class ApplicationComposers {
}
return dds;
}
- return new HashMap<String, URL>();
+ return new HashMap<>();
}
- private static IAnnotationFinder finderFromClasses(final DeploymentModule module, final Class<?>[] value, final Collection<File> others) {
+ private IAnnotationFinder finderFromClasses(final DeploymentModule module, final Class<?>[] value, final Collection<File> others, final String[] excludes) {
final Collection<Archive> archives = new ArrayList<>(1 + (others == null ? 0 : others.size()));
+ final Filter filter = excludes == null || excludes.length == 0 ? null : Filters.invert(Filters.prefixes(excludes));
+
final Collection<Class<?>> classes = new ArrayList<>(asList(FinderFactory.ensureMinimalClasses(module)));
if (value != null) {
classes.addAll(asList(value));
}
- archives.add(new ClassesArchive(classes));
+ final ClassesArchive classesArchive = new ClassesArchive(classes);
+ archives.add(filter == null ? classesArchive : new FilteredArchive(classesArchive, filter));
if (others != null) {
final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
for (final File f : others) {
try {
- archives.add(f.isDirectory() ? new FileArchive(classLoader, f) : new JarArchive(classLoader, f.toURI().toURL()));
+ final Archive archive = f.isDirectory() ? new FileArchive(classLoader, f) : new JarArchive(classLoader, f.toURI().toURL());
+ archives.add(filter == null ? archive : new FilteredArchive(archive, filter));
} catch (final MalformedURLException e) {
throw new IllegalArgumentException(e);
}
@@ -1341,6 +1184,205 @@ public final class ApplicationComposers {
}
}
+ public void startContainer(final Object instance) throws Exception {
+ testClassFinders.remove(this); // see constructor
+
+ // For the moment we just take the first @Configuration method
+ // maybe later we can add something fancy to allow multiple configurations using a qualifier
+ // as a sort of altDD/altConfig concept. Say for example the altDD prefix might be "foo",
+ // we can then imagine something like this:
+ // @Foo @Configuration public Properties alternateConfig(){...}
+ // @Foo @Module public Properties alternateModule(){...}
+ // anyway, one thing at a time ....
+
+ final Properties configuration = new Properties();
+ configuration.put(DEPLOYMENTS_CLASSPATH_PROPERTY, "false");
+
+ final EnableServices annotation = testClass.getAnnotation(EnableServices.class);
+ if (annotation != null && annotation.httpDebug()) {
+ configuration.setProperty("httpejbd.print", "true");
+ configuration.setProperty("httpejbd.indent.xml", "true");
+ configuration.setProperty("logging.level.OpenEJB.server.http", "FINE");
+ }
+ final org.apache.openejb.junit.EnableServices annotationOld = testClass.getAnnotation(org.apache.openejb.junit.EnableServices.class);
+ if (annotationOld != null && annotationOld.httpDebug()) {
+ configuration.setProperty("httpejbd.print", "true");
+ configuration.setProperty("httpejbd.indent.xml", "true");
+ configuration.setProperty("logging.level.OpenEJB.server.http", "FINE");
+ }
+ final WebResource webResource = testClass.getAnnotation(WebResource.class);
+ if (webResource != null && webResource.value().length > 0) {
+ configuration.setProperty("openejb.embedded.http.resources", Join.join(",", webResource.value()));
+ }
+
+ Openejb openejb = null;
+ final Map<Object, List<Method>> configs = new HashMap<>();
+ findAnnotatedMethods(configs, Configuration.class);
+ findAnnotatedMethods(configs, org.apache.openejb.junit.Configuration.class);
+ for (final Map.Entry<Object, List<Method>> method : configs.entrySet()) {
+ for (final Method m : method.getValue()) {
+ final Object o = m.invoke(method.getKey());
+ if (o instanceof Properties) {
+ final Properties properties = (Properties) o;
+ configuration.putAll(properties);
+ } else if (Openejb.class.isInstance(o)) {
+ openejb = Openejb.class.cast(o);
+ } else if (String.class.isInstance(o)) {
+ final String path = String.class.cast(o);
+ final URL url = Thread.currentThread().getContextClassLoader().getResource(path);
+ if (url == null) {
+ throw new IllegalArgumentException(o.toString() + " not found");
+ }
+ final InputStream in = url.openStream();
+ try {
+ if (path.endsWith(".json")) {
+ openejb = JSonConfigReader.read(Openejb.class, in);
+ } else {
+ openejb = JaxbOpenejb.readConfig(new InputSource(in));
+ }
+ } finally {
+ IO.close(in);
+ }
+ }
+ }
+ }
+
+ if (SystemInstance.isInitialized()) {
+ SystemInstance.reset();
+ }
+
+ Collection<String> propertiesToSetAgain = null;
+ final ContainerProperties configAnnot = testClass.getAnnotation(ContainerProperties.class);
+ if (configAnnot != null) {
+ for (final ContainerProperties.Property p : configAnnot.value()) {
+ final String value = p.value();
+ final String name = p.name();
+ configuration.put(name, ContainerProperties.Property.IGNORED.equals(value) ? null : value);
+ if (value.contains("${")) {
+ if (propertiesToSetAgain == null) {
+ propertiesToSetAgain = new LinkedList<>();
+ }
+ propertiesToSetAgain.add(name);
+ }
+ }
+ }
+
+ SystemInstance.init(configuration);
+ for (final Map.Entry<Object, ClassFinder> finder : testClassFinders.entrySet()) {
+ for (final Field field : finder.getValue().findAnnotatedFields(RandomPort.class)) {
+ if (!field.isAccessible()) {
+ field.setAccessible(true);
+ }
+
+ final String service = field.getAnnotation(RandomPort.class).value();
+ final String key = ("http".equals(service) ? "httpejbd" : service) + ".port";
+ final String existing = SystemInstance.get().getProperty(key);
+ final int random;
+ if (existing == null) {
+ random = NetworkUtil.getNextAvailablePort();
+ SystemInstance.get().setProperty(key, Integer.toString(random));
+ } else {
+ random = Integer.parseInt(existing);
+ }
+ if (int.class == field.getType()) {
+ field.set(finder.getKey(), random);
+ } else if (URL.class == field.getType()) {
+ field.set(finder.getKey(), new URL("http://localhost:" + random + "/"));
+ }
+ }
+ }
+
+ for (final Map.Entry<Object, ClassFinder> finder : testClassFinders.entrySet()) {
+ if (!finder.getValue().findAnnotatedClasses(SimpleLog.class).isEmpty()) {
+ SystemInstance.get().setProperty("openejb.jul.forceReload", "true");
+ break;
+ }
+ }
+
+ final CdiExtensions cdiExtensions = testClass.getAnnotation(CdiExtensions.class);
+ if (cdiExtensions != null) {
+ SystemInstance.get().setComponent(LoaderService.class, new ExtensionAwareOptimizedLoaderService(cdiExtensions.value()));
+ }
+
+ // save the test under test to be able to retrieve it from extensions
+ // /!\ has to be done before all other init
+ SystemInstance.get().setComponent(TestInstance.class, new TestInstance(testClass, instance));
+
+ // call the mock injector before module method to be able to use mocked classes
+ // it will often use the TestInstance so
+ final Map<Object, List<Method>> mockInjectors = new HashMap<>();
+ findAnnotatedMethods(mockInjectors, MockInjector.class);
+ findAnnotatedMethods(mockInjectors, org.apache.openejb.junit.MockInjector.class);
+ if (!mockInjectors.isEmpty() && !mockInjectors.values().iterator().next().isEmpty()) {
+ final Map.Entry<Object, List<Method>> methods = mockInjectors.entrySet().iterator().next();
+ Object o = methods.getValue().iterator().next().invoke(methods.getKey());
+ if (o instanceof Class<?>) {
+ o = ((Class<?>) o).newInstance();
+ }
+ if (o instanceof FallbackPropertyInjector) {
+ SystemInstance.get().setComponent(FallbackPropertyInjector.class, (FallbackPropertyInjector) o);
+ }
+ }
+
+ for (final Map.Entry<Object, List<Method>> method : findAnnotatedMethods(new HashMap<Object, List<Method>>(), Component.class).entrySet()) {
+ for (final Method m : method.getValue()) {
+ setComponent(method.getKey(), m);
+ }
+ }
+ for (final Map.Entry<Object, List<Method>> method : findAnnotatedMethods(new HashMap<Object, List<Method>>(), org.apache.openejb.junit.Component.class).entrySet()) {
+ for (final Method m : method.getValue()) {
+ setComponent(method.getKey(), m);
+ }
+ }
+
+ final ConfigurationFactory config = new ConfigurationFactory();
+ config.init(SystemInstance.get().getProperties());
+ SystemInstance.get().setComponent(ConfigurationFactory.class, config);
+
+ assembler = new Assembler();
+ SystemInstance.get().setComponent(Assembler.class, assembler);
+
+ final OpenEjbConfiguration openEjbConfiguration;
+ if (openejb != null) {
+ openEjbConfiguration = config.getOpenEjbConfiguration(openejb);
+ } else {
+ openEjbConfiguration = config.getOpenEjbConfiguration();
+ }
+ assembler.buildContainerSystem(openEjbConfiguration);
+
+ if ("true".equals(configuration.getProperty(OpenEjbContainer.OPENEJB_EMBEDDED_REMOTABLE, "false"))
+ || annotation != null || annotationOld != null) {
+ try {
+ if (annotation != null) {
+ final List<String> value = new ArrayList<>(asList(annotation.value()));
+ if (annotation.jaxrs()) {
+ value.add("jaxrs");
+ }
+ if (annotation.jaxws()) {
+ value.add("jaxws");
+ }
+ initFilteredServiceManager(value.toArray(new String[value.size()]));
+ }
+ if (annotationOld != null) {
+ initFilteredServiceManager(annotationOld.value());
+ }
+ serviceManager = new ServiceManagerProxy(false);
+ serviceManager.start();
+ } catch (final ServiceManagerProxy.AlreadyStartedException e) {
+ throw new OpenEJBRuntimeException(e);
+ }
+ }
+
+ if (propertiesToSetAgain != null) {
+ for (final String name : propertiesToSetAgain) {
+ final String value = PropertyPlaceHolderHelper.simpleValue(SystemInstance.get().getProperty(name));
+ configuration.put(name, value);
+ System.setProperty(name, value); // done lazily to support placeholders so container will not do it here
+ }
+ propertiesToSetAgain.clear();
+ }
+ }
+
protected static class ExtensionAwareOptimizedLoaderService extends OptimizedLoaderService {
private final Class<? extends Extension>[] extensions;
@@ -1432,7 +1474,7 @@ public final class ApplicationComposers {
final Class<?> c = Thread.currentThread().getContextClassLoader().loadClass(args[0]);
- final List<String> a = new ArrayList<String>(asList(args));
+ final List<String> a = new ArrayList<>(asList(args));
a.remove(0);
run(c, a.toArray(new String[a.size()]));
}
http://git-wip-us.apache.org/repos/asf/tomee/blob/7ab0188c/container/openejb-core/src/main/java/org/apache/openejb/testing/Classes.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/testing/Classes.java b/container/openejb-core/src/main/java/org/apache/openejb/testing/Classes.java
index 8eaadca..3806f42 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/testing/Classes.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/testing/Classes.java
@@ -27,6 +27,8 @@ import java.lang.annotation.Target;
public @interface Classes {
Class<?>[] value() default {};
+ String[] excludes() default {};
+
Class<?>[] cdiInterceptors() default {};
Class<?>[] cdiDecorators() default {};
http://git-wip-us.apache.org/repos/asf/tomee/blob/7ab0188c/container/openejb-core/src/main/java/org/apache/openejb/util/StringTemplate.java
----------------------------------------------------------------------
diff --git a/container/openejb-core/src/main/java/org/apache/openejb/util/StringTemplate.java b/container/openejb-core/src/main/java/org/apache/openejb/util/StringTemplate.java
index f57fe5f..0d0a442 100644
--- a/container/openejb-core/src/main/java/org/apache/openejb/util/StringTemplate.java
+++ b/container/openejb-core/src/main/java/org/apache/openejb/util/StringTemplate.java
@@ -54,7 +54,7 @@ public class StringTemplate {
if (value == null) {
throw new IllegalStateException("Value is null for key '" + key + "'. Template '" + template + "'. Keys: " + Join.join(", ", map.keySet()));
}
- matcher.appendReplacement(buf, value);
+ matcher.appendReplacement(buf, value.replace("$", "\\$")); // inner class have a $ we need to escape cause it means sthg for regex
}
matcher.appendTail(buf);