
org.jglue.cdiunit.internal.WeldTestUrlDeployment Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cdi-unit Show documentation
Show all versions of cdi-unit Show documentation
JUnit runner for testing CDI based projects.
/*
* Copyright 2011 Bryn Cooke
*
* Licensed 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.jglue.cdiunit.internal;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.jar.Attributes;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.Stereotype;
import javax.enterprise.inject.spi.Extension;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.interceptor.Interceptor;
import org.jboss.weld.bootstrap.api.Bootstrap;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.api.helpers.SimpleServiceRegistry;
import org.jboss.weld.bootstrap.spi.BeanDeploymentArchive;
import org.jboss.weld.bootstrap.spi.BeanDiscoveryMode;
import org.jboss.weld.bootstrap.spi.BeansXml;
import org.jboss.weld.bootstrap.spi.Deployment;
import org.jboss.weld.bootstrap.spi.Metadata;
import org.jboss.weld.bootstrap.spi.Scanning;
import org.jboss.weld.environment.se.WeldSEBeanRegistrant;
import org.jboss.weld.metadata.BeansXmlImpl;
import org.jboss.weld.metadata.MetadataImpl;
import org.jboss.weld.resources.spi.ResourceLoader;
import org.jglue.cdiunit.*;
import org.jglue.cdiunit.internal.easymock.EasyMockExtension;
import org.jglue.cdiunit.internal.jsf.ViewScopeExtension;
import org.jglue.cdiunit.internal.mockito.MockitoExtension;
import org.jglue.cdiunit.internal.servlet.MockHttpServletRequestImpl;
import org.jglue.cdiunit.internal.servlet.MockHttpServletResponseImpl;
import org.jglue.cdiunit.internal.servlet.MockHttpSessionImpl;
import org.jglue.cdiunit.internal.servlet.MockServletContextImpl;
import org.jglue.cdiunit.internal.servlet.ServletObjectsProducer;
import org.mockito.Mock;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Predicate;
public class WeldTestUrlDeployment implements Deployment {
private final BeanDeploymentArchive beanDeploymentArchive;
private Collection> extensions = new ArrayList>();
private static Logger log = LoggerFactory.getLogger(WeldTestUrlDeployment.class);
private Set cdiClasspathEntries = new HashSet();
private final ServiceRegistry serviceRegistry = new SimpleServiceRegistry();
public WeldTestUrlDeployment(ResourceLoader resourceLoader, Bootstrap bootstrap, Class> testClass) throws IOException {
populateCdiClasspathSet();
BeansXml beansXml;
try {
beansXml = new BeansXmlImpl(new ArrayList>(), new ArrayList>(),
new ArrayList>(), new ArrayList>(), Scanning.EMPTY_SCANNING, new URL(
"file:cdi-unit"), BeanDiscoveryMode.ALL, "cdi-unit");
} catch (NoClassDefFoundError e) {
try {
beansXml = (BeansXml) BeansXmlImpl.class.getConstructors()[0].newInstance(new ArrayList>(),
new ArrayList>(), new ArrayList>(), new ArrayList>(),
Scanning.EMPTY_SCANNING);
} catch (Exception e1) {
throw new RuntimeException(e1);
}
}
Set discoveredClasses = new LinkedHashSet();
Set alternatives = new HashSet();
discoveredClasses.add(testClass.getName());
Set> classesToProcess = new LinkedHashSet>();
Set> classesProcessed = new HashSet>();
Set> classesToIgnore = findMockedClassesOfTest(testClass);
classesToProcess.add(testClass);
extensions.add(new MetadataImpl(new TestScopeExtension(testClass), TestScopeExtension.class.getName()));
try {
Class.forName("javax.faces.view.ViewScoped");
extensions.add(new MetadataImpl(new ViewScopeExtension(), ViewScopeExtension.class.getName()));
} catch (ClassNotFoundException e) {
}
try {
Class.forName("javax.servlet.http.HttpServletRequest");
classesToProcess.add(InRequestInterceptor.class);
classesToProcess.add(InSessionInterceptor.class);
classesToProcess.add(InConversationInterceptor.class);
discoveredClasses.add(CdiUnitInitialListener.class.getName());
classesToProcess.add(MockServletContextImpl.class);
classesToProcess.add(MockHttpSessionImpl.class);
classesToProcess.add(MockHttpServletRequestImpl.class);
classesToProcess.add(MockHttpServletResponseImpl.class);
// If this is an old version of weld then add the producers
try {
Class.forName("org.jboss.weld.bean.AbstractSyntheticBean");
} catch (ClassNotFoundException e) {
classesToProcess.add(ServletObjectsProducer.class);
}
} catch (ClassNotFoundException e) {
}
while (!classesToProcess.isEmpty()) {
Class> c = classesToProcess.iterator().next();
if ((isCdiClass(c) || Extension.class.isAssignableFrom(c)) && !classesProcessed.contains(c) && !c.isPrimitive()
&& !classesToIgnore.contains(c)) {
classesProcessed.add(c);
if (!c.isAnnotation()) {
discoveredClasses.add(c.getName());
}
if (Extension.class.isAssignableFrom(c) && !Modifier.isAbstract(c.getModifiers())) {
try {
extensions.add(new MetadataImpl((Extension) c.newInstance(), c.getName()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (c.isAnnotationPresent(Interceptor.class)) {
beansXml.getEnabledInterceptors().add(new MetadataImpl(c.getName(), c.getName()));
}
if (isAlternativeStereotype(c)) {
beansXml.getEnabledAlternativeStereotypes().add(new MetadataImpl(c.getName(), c.getName()));
}
AdditionalClasses additionalClasses = c.getAnnotation(AdditionalClasses.class);
if (additionalClasses != null) {
for (Class> supportClass : additionalClasses.value()) {
classesToProcess.add(supportClass);
}
for (String lateBound : additionalClasses.late()) {
try {
Class> clazz = Class.forName(lateBound);
classesToProcess.add(clazz);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
AdditionalClasspaths additionalClasspaths = c.getAnnotation(AdditionalClasspaths.class);
if (additionalClasspaths != null) {
for (Class> additionalClasspath : additionalClasspaths.value()) {
Reflections reflections = new Reflections(new ConfigurationBuilder().setScanners(new TypesScanner())
.setUrls(
new File(additionalClasspath.getProtectionDomain().getCodeSource().getLocation()
.getPath()).toURI().toURL()));
classesToProcess.addAll(ReflectionUtils.forNames(
reflections.getStore().get(TypesScanner.class.getSimpleName()).keySet(),
new ClassLoader[] { getClass().getClassLoader() }));
}
}
AdditionalPackages additionalPackages = c.getAnnotation(AdditionalPackages.class);
if (additionalPackages != null) {
for (Class> additionalPackage : additionalPackages.value()) {
final String packageName = additionalPackage.getPackage().getName();
Reflections reflections = new Reflections(new ConfigurationBuilder()
.setScanners(new TypesScanner())
.setUrls(
new File(additionalPackage.getProtectionDomain().getCodeSource().getLocation().getPath())
.toURI().toURL()).filterInputsBy(new Predicate() {
@Override
public boolean apply(String input) {
return input.startsWith(packageName)
&& !input.substring(packageName.length() + 1, input.length() - 6).contains(".");
}
}));
classesToProcess.addAll(ReflectionUtils.forNames(
reflections.getStore().get(TypesScanner.class.getSimpleName()).keySet(),
new ClassLoader[] { getClass().getClassLoader() }));
}
}
ActivatedAlternatives alternativeClasses = c.getAnnotation(ActivatedAlternatives.class);
if (alternativeClasses != null) {
for (Class> alternativeClass : alternativeClasses.value()) {
classesToProcess.add(alternativeClass);
if (!isAlternativeStereotype(alternativeClass)) {
alternatives.add(alternativeClass.getName());
}
}
}
for (Annotation a : c.getAnnotations()) {
if (!a.annotationType().getPackage().getName().equals("org.jglue.cdiunit")) {
classesToProcess.add(a.annotationType());
}
}
Type superClass = c.getGenericSuperclass();
if (superClass != null && superClass != Object.class) {
addClassesToProcess(classesToProcess, superClass);
}
for (Field field : c.getDeclaredFields()) {
if (field.isAnnotationPresent(Inject.class) || field.isAnnotationPresent(Produces.class)) {
addClassesToProcess(classesToProcess, field.getGenericType());
}
if (field.getType().equals(Provider.class) || field.getType().equals(Instance.class)) {
addClassesToProcess(classesToProcess, field.getGenericType());
}
}
for (Method method : c.getDeclaredMethods()) {
if (method.isAnnotationPresent(Inject.class) || method.isAnnotationPresent(Produces.class)) {
for (Type param : method.getGenericParameterTypes()) {
addClassesToProcess(classesToProcess, param);
}
addClassesToProcess(classesToProcess, method.getGenericReturnType());
}
}
}
classesToProcess.remove(c);
}
beansXml.getEnabledAlternativeStereotypes().add(
new MetadataImpl(ProducesAlternative.class.getName(), ProducesAlternative.class.getName()));
for (String alternative : alternatives) {
beansXml.getEnabledAlternativeClasses().add(new MetadataImpl(alternative, alternative));
}
try {
Class.forName("org.mockito.Mock");
extensions.add(new MetadataImpl(new MockitoExtension(), MockitoExtension.class.getName()));
} catch (ClassNotFoundException e) {
}
try {
Class.forName("org.easymock.EasyMockRunner");
extensions.add(new MetadataImpl(new EasyMockExtension(), EasyMockExtension.class.getName()));
} catch (ClassNotFoundException e) {
}
extensions.add(new MetadataImpl(new WeldSEBeanRegistrant(), WeldSEBeanRegistrant.class.getName()));
beanDeploymentArchive = new BeanDeploymentArchiveImpl("cdi-unit" + UUID.randomUUID(), discoveredClasses, beansXml);
beanDeploymentArchive.getServices().add(ResourceLoader.class, resourceLoader);
log.debug("CDI-Unit discovered:");
for (String clazz : discoveredClasses) {
if (!clazz.startsWith("org.jglue.cdiunit.internal.")) {
log.debug(clazz);
}
}
}
private void addClassesToProcess(Collection> classesToProcess, Type type) {
if (type instanceof Class) {
classesToProcess.add((Class>)type);
}
if(type instanceof ParameterizedType) {
ParameterizedType ptype = (ParameterizedType)type;
classesToProcess.add((Class>)ptype.getRawType());
for(Type arg : ptype.getActualTypeArguments()) {
addClassesToProcess(classesToProcess, arg);
}
}
}
private Set> findMockedClassesOfTest(Class> testClass) {
Set> mockedClasses = new HashSet>();
try {
for (Field field : testClass.getDeclaredFields()) {
if (field.isAnnotationPresent(Mock.class)) {
Class> type = field.getType();
mockedClasses.add(type);
}
}
} catch (NoClassDefFoundError e) {
}
try {
for (Field field : testClass.getDeclaredFields()) {
if (field.isAnnotationPresent(org.easymock.Mock.class)) {
Class> type = field.getType();
mockedClasses.add(type);
}
}
} catch (NoClassDefFoundError e) {
}
return mockedClasses;
}
private void populateCdiClasspathSet() throws IOException {
ClassLoader classLoader = WeldTestUrlDeployment.class.getClassLoader();
List entries = new ArrayList(Arrays.asList(((URLClassLoader) classLoader).getURLs()));
// If this is surefire we need to get the original claspath
JarInputStream firstEntry = new JarInputStream(entries.get(0).openStream());
Manifest manifest = firstEntry.getManifest();
if (manifest != null) {
String classpath = (String) manifest.getMainAttributes().get(Attributes.Name.CLASS_PATH);
if (classpath != null) {
String[] manifestEntries = classpath.split(" ?file:");
for (String entry : manifestEntries) {
if (entry.length() > 0) {
entries.add(new URL("file:" + entry));
}
}
}
}
firstEntry.close();
for (URL url : entries) {
URLClassLoader cl = new URLClassLoader(new URL[] { url }, null);
try {
if (url.getFile().endsWith("/classes/")) {
URL webInfBeans = new URL(url, "../../src/main/webapp/WEB-INF/beans.xml");
try {
webInfBeans.openConnection();
cdiClasspathEntries.add(url);
} catch (IOException e) {
}
}
URL resource = cl.getResource("META-INF/beans.xml");
boolean cdiUnit = url.equals(CdiRunner.class.getProtectionDomain().getCodeSource().getLocation());
boolean mavenClasses = url.getFile().endsWith("/test-classes/");
boolean generatedClasses = url.getFile().contains("/generated-classes/");
boolean gradleClasses = url.getFile().endsWith("/classes/test/") || url.getFile().endsWith("/classes/main/");
if (cdiUnit || resource != null || mavenClasses || gradleClasses || generatedClasses) {
cdiClasspathEntries.add(url);
}
} finally {
try {
Method method = cl.getClass().getMethod("close");
method.invoke(cl);
} catch (NoSuchMethodException e) {
//Ignore, we might be running on Java 6
} catch (IllegalAccessException e) {
//Ignore, we might be running on Java 6
} catch (InvocationTargetException e) {
//Ignore, we might be running on Java 6
}
}
}
log.debug("CDI classpath entries discovered:");
for (URL url : cdiClasspathEntries) {
log.debug("{}", url);
}
}
private boolean isCdiClass(Class> c) {
if (c.getProtectionDomain().getCodeSource() == null) {
return false;
}
URL location = c.getProtectionDomain().getCodeSource().getLocation();
boolean isCdi = cdiClasspathEntries.contains(location);
return isCdi;
}
private boolean isAlternativeStereotype(Class> c) {
return c.isAnnotationPresent(Stereotype.class) && c.isAnnotationPresent(Alternative.class);
}
@Override
public Iterable> getExtensions() {
return extensions;
}
public List getBeanDeploymentArchives() {
return Collections.singletonList(beanDeploymentArchive);
}
public BeanDeploymentArchive loadBeanDeploymentArchive(Class> beanClass) {
return beanDeploymentArchive;
}
public BeanDeploymentArchive getBeanDeploymentArchive(Class> beanClass) {
return beanDeploymentArchive;
}
@Override
public ServiceRegistry getServices() {
return serviceRegistry;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy