Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
carlosmunoz
Author
Member
|
||
* @author tags. See the copyright.txt file in the distribution for a full | ||
* listing of individual contributors. | ||
* | ||
* This is free software; you can redistribute it and/or modify it under the | ||
* terms of the GNU Lesser General Public License as published by the Free | ||
* Software Foundation; either version 2.1 of the License, or (at your option) | ||
* any later version. | ||
* | ||
* This software is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this software; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF | ||
* site: http://www.fsf.org. | ||
*/ | ||
package org.zanata.cdi; | ||
|
||
import com.google.inject.Binder; | ||
import com.google.inject.TypeLiteral; | ||
import org.zanata.events.AlreadyLoggedInEvent; | ||
import org.zanata.events.LoginFailedEvent; | ||
import org.zanata.events.LoginSuccessfulEvent; | ||
import org.zanata.events.LogoutEvent; | ||
import org.zanata.events.NotLoggedInEvent; | ||
|
||
import javax.enterprise.event.Event; | ||
import java.lang.annotation.Annotation; | ||
import java.util.function.Consumer; | ||
|
||
/** | ||
* @author Carlos Munoz <a href="mailto:camunoz@redhat.com">camunoz@redhat.com</a> | ||
*/ | ||
public final class AutowireUtils { | ||
|
||
private static final Consumer<Binder> MOCK_EVENTS = binder -> { | ||
binder.bind(new TypeLiteral<Event<AlreadyLoggedInEvent>>(){}).toProvider( | ||
MockProvider.of(new TypeLiteral<Event<AlreadyLoggedInEvent>>(){})); | ||
binder.bind(new TypeLiteral<Event<LoginFailedEvent>>(){}).toProvider( | ||
MockProvider.of(new TypeLiteral<Event<LoginFailedEvent>>(){})); | ||
binder.bind(new TypeLiteral<Event<LoginSuccessfulEvent>>(){}).toProvider( | ||
MockProvider.of(new TypeLiteral<Event<LoginSuccessfulEvent>>(){})); | ||
binder.bind(new TypeLiteral<Event<LogoutEvent>>(){}).toProvider( | ||
MockProvider.of(new TypeLiteral<Event<LogoutEvent>>(){})); | ||
binder.bind(new TypeLiteral<Event<NotLoggedInEvent>>(){}).toProvider( | ||
MockProvider.of(new TypeLiteral<Event<NotLoggedInEvent>>(){})); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
carlosmunoz
Author
Member
|
||
}; | ||
|
||
private AutowireUtils() { | ||
} | ||
|
||
public static void mockInstances(Class cls, Binder binder) { | ||
binder.bind(cls).toProvider(MockProvider.of(cls)); | ||
} | ||
|
||
public static void mockInstances(Class cls, | ||
Class<? extends Annotation> annotatedWith, Binder binder) { | ||
binder.bind(cls).annotatedWith(annotatedWith) | ||
This comment has been minimized.
Sorry, something went wrong.
seanf
Contributor
|
||
.toProvider(MockProvider.of(cls)); | ||
} | ||
|
||
public static Consumer<Binder> mockEvents() { | ||
return MOCK_EVENTS; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
/* | ||
* Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the | ||
* @author tags. See the copyright.txt file in the distribution for a full | ||
* listing of individual contributors. | ||
* | ||
* This is free software; you can redistribute it and/or modify it under the | ||
* terms of the GNU Lesser General Public License as published by the Free | ||
* Software Foundation; either version 2.1 of the License, or (at your option) | ||
* any later version. | ||
* | ||
* This software is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this software; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF | ||
* site: http://www.fsf.org. | ||
*/ | ||
package org.zanata.cdi; | ||
|
||
import com.google.inject.AbstractModule; | ||
import com.google.inject.Binder; | ||
import com.google.inject.Guice; | ||
import com.google.inject.Injector; | ||
import com.google.inject.Module; | ||
import com.google.inject.Scopes; | ||
import com.google.inject.TypeLiteral; | ||
import com.google.inject.binder.AnnotatedBindingBuilder; | ||
import com.google.inject.matcher.AbstractMatcher; | ||
import com.google.inject.spi.InjectionListener; | ||
import com.google.inject.spi.TypeEncounter; | ||
import com.google.inject.spi.TypeListener; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.apache.deltaspike.core.api.exclude.Exclude; | ||
import org.apache.deltaspike.core.api.projectstage.ProjectStage; | ||
import org.mockito.Mockito; | ||
import org.zanata.seam.AutowireException; | ||
import org.zanata.util.CDIAutowireLocator; | ||
import org.zanata.util.IServiceLocator; | ||
|
||
import javax.enterprise.context.Dependent; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.function.Consumer; | ||
|
||
/** | ||
* @author Carlos Munoz <a href="mailto:camunoz@redhat.com">camunoz@redhat.com</a> | ||
*/ | ||
@Slf4j | ||
@Exclude(ifProjectStage = ProjectStage.IntegrationTest.class) | ||
public class CDIAutowire { | ||
|
||
private Injector injector; | ||
private Consumer<Binder> binderConfiguration; | ||
|
||
private final Consumer<Binder> staticConfig = binder -> { | ||
// add mandatory bindings | ||
// Service Locator | ||
binder.bind(IServiceLocator.class).toInstance(new CDIAutowireLocator(this)); | ||
// Invoke @PostConstruct methods | ||
binder.bindListener(new AbstractMatcher<TypeLiteral<?>>() { | ||
@Override | ||
public boolean matches(TypeLiteral<?> typeLiteral) { | ||
return true; // check all components | ||
} | ||
}, new TypeListener() { | ||
@Override | ||
public <I> void hear(TypeLiteral<I> type, | ||
TypeEncounter<I> encounter) { | ||
encounter.register((InjectionListener<I>) injectee -> { | ||
invokePostConstructMethod(injectee); | ||
}); | ||
} | ||
}); | ||
// Bind the dependent scope | ||
// TODO Other scopes? | ||
binder.bindScope(Dependent.class, Scopes.NO_SCOPE); | ||
}; | ||
|
||
public final CDIAutowire configure(Consumer<Binder> configure) { | ||
composeBinderConfiguration(configure); | ||
return this; | ||
} | ||
|
||
public Injector getInjector() { | ||
if(injector == null) { | ||
injector = createInjector(); | ||
} | ||
return injector; | ||
} | ||
|
||
private void composeBinderConfiguration(Consumer<Binder> postConsumer) { | ||
if(binderConfiguration == null) { | ||
binderConfiguration = postConsumer; | ||
} else { | ||
binderConfiguration = binderConfiguration.andThen(postConsumer); | ||
} | ||
} | ||
|
||
private Injector createInjector() { | ||
Consumer<Binder> fullConfig = binderConfiguration.andThen(staticConfig); | ||
// Build a regular module which runs the statically provided configuration | ||
Module originalModule = new AbstractModule() { | ||
@Override | ||
protected void configure() { | ||
fullConfig.accept(binder()); | ||
} | ||
}; | ||
|
||
return Guice.createInjector(originalModule); | ||
} | ||
|
||
private static void bindMissingDependency(Binder binder, | ||
InjectionErrorExtractor.MissingDependency dep) { | ||
Class dependencyType = dep.getDependencyType(); | ||
// binf the missing dependency | ||
AnnotatedBindingBuilder builder = | ||
binder.bind(dependencyType); | ||
// If there is a provided annotation qualifier | ||
if(dep.getAnnotation() != null) { | ||
builder.annotatedWith(dep.getAnnotation()); | ||
} | ||
// Special case: Strings | ||
if(String.class.equals(dependencyType)) { | ||
builder.toInstance("Mock value (please bind)"); | ||
} else { | ||
builder.toInstance(Mockito.mock(dependencyType)); | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Invokes a single method (the first found) annotated with | ||
* {@link javax.annotation.PostConstruct}, | ||
*/ | ||
private static void invokePostConstructMethod(Object bean) { | ||
Class<?> compClass = bean.getClass(); | ||
boolean postConstructAlreadyFound = false; | ||
|
||
for (Method m : compClass.getDeclaredMethods()) { | ||
// Per the spec, there should be only one PostConstruct method | ||
if (m.getAnnotation(javax.annotation.PostConstruct.class) != null) { | ||
if (postConstructAlreadyFound) { | ||
throw new AutowireException("More than one PostConstruct method found for class " | ||
+ compClass.getName()); | ||
} | ||
try { | ||
m.setAccessible(true); | ||
m.invoke(bean); // there should be no params | ||
postConstructAlreadyFound = true; | ||
} catch (IllegalAccessException | InvocationTargetException e) { | ||
throw new AutowireException( | ||
"Error invoking PostConstruct method in bean of class " | ||
+ compClass.getName(), e); | ||
} | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright 2010, Red Hat, Inc. and individual contributors as indicated by the | ||
* @author tags. See the copyright.txt file in the distribution for a full | ||
* listing of individual contributors. | ||
* | ||
* This is free software; you can redistribute it and/or modify it under the | ||
* terms of the GNU Lesser General Public License as published by the Free | ||
* Software Foundation; either version 2.1 of the License, or (at your option) | ||
* any later version. | ||
* | ||
* This software is distributed in the hope that it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
* details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this software; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF | ||
* site: http://www.fsf.org. | ||
*/ | ||
package org.zanata.util; | ||
|
||
|
||
import java.lang.annotation.Annotation; | ||
import java.util.Optional; | ||
|
||
import javax.enterprise.inject.Alternative; | ||
import javax.naming.NamingException; | ||
import javax.persistence.EntityManager; | ||
import javax.persistence.EntityManagerFactory; | ||
|
||
import com.google.inject.Injector; | ||
import org.apache.deltaspike.core.api.exclude.Exclude; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.zanata.cdi.CDIAutowire; | ||
import org.zanata.seam.SeamAutowire; | ||
|
||
/** | ||
* Replacement class for our ServiceLocator. Tests that use | ||
* the {@link org.zanata.cdi.CDIAutowire} class will use this class instead of | ||
* the real one ({@Link org.zanata.util.ServiceLocator}) to request components. | ||
* | ||
* @author Carlos Munoz <a | ||
* href="mailto:camunoz@redhat.com">camunoz@redhat.com</a> | ||
*/ | ||
@Alternative | ||
@Exclude | ||
public class CDIAutowireLocator implements IServiceLocator { | ||
private static final Logger log = | ||
LoggerFactory.getLogger(AutowireLocator.class); | ||
|
||
private final CDIAutowire autowire; | ||
|
||
public CDIAutowireLocator() { | ||
this(new CDIAutowire()); | ||
} | ||
|
||
public CDIAutowireLocator(CDIAutowire autowire) { | ||
this.autowire = autowire; | ||
} | ||
|
||
public <T> BeanHolder<T> getDependent(Class<T> clazz, Annotation... qualifiers) { | ||
return new BeanHolder<T>(getInstance(clazz, qualifiers)); | ||
} | ||
|
||
public <T> T getInstance(Class<T> clazz, Annotation... qualifiers) { | ||
// try { | ||
// if (!SeamAutowire.disableRealServiceLocator) { | ||
// T bean = ServiceLocator.INSTANCE.getInstance(clazz, | ||
// qualifiers); | ||
// log.debug("Returning CDI bean: {}", bean); | ||
// return bean; | ||
// } | ||
// } catch (IllegalStateException e) { | ||
// log.debug("Can't find CDI bean, trying SeamAutowire", | ||
// e.getMessage()); | ||
// } | ||
// TODO Figure out how to do qualifiers | ||
return autowire.getInjector().getInstance(clazz); | ||
} | ||
|
||
public <T> Optional<T> getOptionalInstance(Class<T> clazz, Annotation... qualifiers) { | ||
// TODO Figure out how to do qualifiers | ||
return Optional.ofNullable(autowire.getInjector().getInstance(clazz)); | ||
} | ||
|
||
@Override | ||
public EntityManager getEntityManager() { | ||
return getInstance(EntityManager.class); | ||
} | ||
|
||
@Override | ||
public EntityManagerFactory getEntityManagerFactory() { | ||
return getInstance(EntityManagerFactory.class); | ||
} | ||
|
||
@Override | ||
public <T> T getJndiComponent(String jndiName, Class<T> clazz) | ||
throws NamingException { | ||
T instance = (T) SeamAutowire.instance().getComponent(jndiName); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
carlosmunoz
Author
Member
|
||
if (instance == null) { | ||
throw new NamingException("component with JNDI name " + jndiName + | ||
" has not been registered with Autowire"); | ||
} | ||
return instance; | ||
} | ||
|
||
} |
1 comment
on commit ddae74d
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to look at the class org.jglue.cdiunit.internal.WeldTestUrlDeployment in CDI-Unit. It does most of the work in CDI-Unit, creating a deployment context for Weld SE, a bit like building up a Guice module and its bindings.
I guess we could always use something like org.atteo.classindex.processor.ClassIndexProcessor to index the package org.zanata.events. Any solution is going to be a bit toe-curling if Guice is fighting us though.
Let's hope the world doesn't end in 2012, eh?