Repository: deltaspike Updated Branches: refs/heads/master 5b5be22f0 -> 7ad36c14c
DELTASPIKE-834 fix MessageBundleExtension in EARs * remove bean wrapping and use native proxying instead * clean up BeanBuilder module Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/7ad36c14 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/7ad36c14 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/7ad36c14 Branch: refs/heads/master Commit: 7ad36c14c22df3bb0b156a397766af29892f0bcf Parents: 5b5be22 Author: Mark Struberg <[email protected]> Authored: Tue Feb 17 14:52:51 2015 +0100 Committer: Mark Struberg <[email protected]> Committed: Tue Feb 17 14:52:51 2015 +0100 ---------------------------------------------------------------------- .../core/api/provider/BeanProvider.java | 11 + .../deltaspike/core/util/bean/BeanBuilder.java | 79 ++-- .../core/util/bean/WrappingBeanBuilder.java | 383 +------------------ .../util/metadata/InjectionPointWrapper.java | 4 +- .../impl/message/MessageBundleExtension.java | 232 ++--------- .../NamedMessageBundleInvocationHandler.java | 96 ----- .../impl/message/NamedTypedMessageBundle.java | 41 -- .../message/NamedTypedMessageBundleLiteral.java | 28 -- .../core/impl/message/TypedMessageBundle.java | 44 --- .../message/TypedMessageBundleProducer.java | 80 ---- .../test/jsf/impl/message/JsfMessageTest.java | 6 + .../jsf/impl/message/beans/UserMessage.java | 3 + .../test/resources/jsfMessageTest/page.xhtml | 10 + 13 files changed, 128 insertions(+), 889 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java index bcf2b8d..e5674ce 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/provider/BeanProvider.java @@ -339,6 +339,12 @@ public final class BeanProvider public static <T> DependentProvider<T> getDependent(Class<T> type, Annotation... qualifiers) { BeanManager beanManager = getBeanManager(); + return getDependent(beanManager, type, qualifiers); + } + + public static <T> DependentProvider<T> getDependent(BeanManager beanManager, Class<T> type, + Annotation... qualifiers) + { Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers); @SuppressWarnings("unchecked") Bean<T> bean = (Bean<T>) beanManager.resolve(beans); @@ -348,6 +354,11 @@ public final class BeanProvider public static <T> DependentProvider<T> getDependent(String name) { BeanManager beanManager = getBeanManager(); + return getDependent(beanManager, name); + } + + public static <T> DependentProvider<T> getDependent(BeanManager beanManager, String name) + { Set<Bean<?>> beans = beanManager.getBeans(name); @SuppressWarnings("unchecked") Bean<T> bean = (Bean<T>) beanManager.resolve(beans); http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/BeanBuilder.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/BeanBuilder.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/BeanBuilder.java index aecea93..5180763 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/BeanBuilder.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/BeanBuilder.java @@ -36,6 +36,7 @@ import javax.enterprise.inject.spi.InjectionPoint; import javax.enterprise.inject.spi.InjectionTarget; import javax.inject.Named; +import java.beans.Introspector; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.Arrays; @@ -59,25 +60,24 @@ import java.util.Set; * It is advised that a new bean builder is instantiated for each bean created. * </p> */ -// X TODO: Add tests public class BeanBuilder<T> { - private final BeanManager beanManager; + protected final BeanManager beanManager; - private Class<?> beanClass; - private String name; - private Set<Annotation> qualifiers; - private Class<? extends Annotation> scope; - private Set<Class<? extends Annotation>> stereotypes; - private Set<Type> types; - private Set<InjectionPoint> injectionPoints; - private boolean alternative; - private boolean nullable; - private ContextualLifecycle<T> beanLifecycle; - private boolean passivationCapable; - private String id; - private String toString; + protected Class<?> beanClass; + protected String name; + protected Set<Annotation> qualifiers; + protected Class<? extends Annotation> scope = Dependent.class; + protected Set<Class<? extends Annotation>> stereotypes; + protected Set<Type> types; + protected Set<InjectionPoint> injectionPoints; + protected boolean alternative; + protected boolean nullable; + protected ContextualLifecycle<T> beanLifecycle; + protected boolean passivationCapable; + protected String id; + protected String toString; /** * Instantiate a new bean builder. @@ -112,17 +112,12 @@ public class BeanBuilder<T> public BeanBuilder<T> readFromType(AnnotatedType<T> type) { this.beanClass = type.getJavaClass(); - InjectionTarget<T> injectionTarget; - if (!type.getJavaClass().isInterface()) - { - injectionTarget = beanManager.createInjectionTarget(type); - } - else + + if (beanLifecycle == null) { - injectionTarget = new DummyInjectionTarget<T>(); + setDefaultBeanLifecycle(type); } - this.beanLifecycle = new DelegatingContextualLifecycle<T>(injectionTarget); - this.injectionPoints = injectionTarget.getInjectionPoints(); + this.qualifiers = new HashSet<Annotation>(); this.stereotypes = new HashSet<Class<? extends Annotation>>(); this.types = new HashSet<Type>(); @@ -143,16 +138,16 @@ public class BeanBuilder<T> if (annotation instanceof Named) { this.name = ((Named) annotation).value(); + if (name == null || name.length() == 0) + { + name = createDefaultBeanName(type); + } } if (annotation instanceof Alternative) { this.alternative = true; } } - if (this.scope == null) - { - this.scope = Dependent.class; - } if (type.isAnnotationPresent(Typed.class)) { Typed typed = type.getAnnotation(Typed.class); @@ -170,15 +165,43 @@ public class BeanBuilder<T> this.types.add(i); } } + if (qualifiers.isEmpty()) { qualifiers.add(new DefaultLiteral()); } qualifiers.add(new AnyLiteral()); + this.id = ImmutableBeanWrapper.class.getName() + ":" + Annotateds.createTypeId(type); return this; } + private String createDefaultBeanName(AnnotatedType<T> type) + { + Class<T> javaClass = type.getJavaClass(); + return Introspector.decapitalize(javaClass.getSimpleName()); + } + + + /** + * Set the ContextualLifecycle and the InjectionPoints for the AnnotatedType + * @param type + */ + protected void setDefaultBeanLifecycle(AnnotatedType<T> type) + { + InjectionTarget<T> injectionTarget; + if (!type.getJavaClass().isInterface()) + { + injectionTarget = beanManager.createInjectionTarget(type); + } + else + { + injectionTarget = new DummyInjectionTarget<T>(); + } + this.beanLifecycle = new DelegatingContextualLifecycle<T>(injectionTarget); + this.injectionPoints = injectionTarget.getInjectionPoints(); + } + /** * <p> * Use the bean builder's current state to define the bean. http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/WrappingBeanBuilder.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/WrappingBeanBuilder.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/WrappingBeanBuilder.java index d6f78ff..a189a95 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/WrappingBeanBuilder.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/bean/WrappingBeanBuilder.java @@ -18,21 +18,9 @@ */ package org.apache.deltaspike.core.util.bean; -import org.apache.deltaspike.core.api.literal.AnyLiteral; -import org.apache.deltaspike.core.api.literal.DefaultLiteral; -import org.apache.deltaspike.core.util.ArraysUtils; - -import javax.enterprise.context.Dependent; -import javax.enterprise.inject.Alternative; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; -import javax.inject.Named; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; /** * <p>A WrappingBeanBuilder helps creating Beans which internally @@ -45,21 +33,10 @@ import java.util.Set; * * @param <T> the type of the Bean */ -public class WrappingBeanBuilder<T> +public class WrappingBeanBuilder<T> extends BeanBuilder<T> { private final Bean<T> delegate; - private final BeanManager beanManager; - private Set<Type> types; - private Set<Annotation> qualifiers; - private String name; - private Class<? extends Annotation> scope; - private boolean alternative; - private boolean nullable; - private String toString; - private Set<Class<? extends Annotation>> stereotypes; - private boolean passivationCapable; - private String id; /** * Instantiate a new {@link WrappingBeanBuilder}. @@ -69,275 +46,13 @@ public class WrappingBeanBuilder<T> */ public WrappingBeanBuilder(Bean<Object> delegate, BeanManager beanManager) { + super(beanManager); this.delegate = (Bean<T>) delegate; - this.beanManager = beanManager; - } - - /** - * <p> - * Read the {@link AnnotatedType}, creating a narrowing bean from the class - * and its annotations. - * </p> - * - * @param type the type to read - */ - public WrappingBeanBuilder<T> readFromType(AnnotatedType<T> type) - { - types = new HashSet<Type>(type.getTypeClosure()); - qualifiers = new HashSet<Annotation>(); - stereotypes = new HashSet<Class<? extends Annotation>>(); - String name = null; - Class<? extends Annotation> scope = Dependent.class; - - for (Annotation annotation : type.getAnnotations()) - { - if (annotation.annotationType().equals(Named.class)) - { - // it's important to scan for Named first - // as it's also a qualifier! - name = Named.class.cast(annotation).value(); - } - else if (beanManager.isQualifier(annotation.annotationType())) - { - qualifiers.add(annotation); - } - else if (beanManager.isScope(annotation.annotationType())) - { - scope = annotation.annotationType(); - } - else if (beanManager.isStereotype(annotation.annotationType())) - { - stereotypes.add(annotation.annotationType()); - } - } - if (qualifiers.isEmpty()) - { - qualifiers.add(new DefaultLiteral()); - } - qualifiers.add(new AnyLiteral()); - this.name = "".equals(name) ? null : name; - this.scope = scope; - alternative = type.isAnnotationPresent(Alternative.class); - return this; - } - - /** - * Type closure currently defined for bean creation. - * - * @return the type closure currently defined - */ - public Set<Type> getTypes() - { - return types; - } - - /** - * Define the type closure used for bean creation. - * - * @param types the type closure to use - */ - public WrappingBeanBuilder<T> types(Set<Type> types) - { - this.types = types; - return this; - } - - /** - * Define the type closure used for bean creation. - * - * @param types the type closure to use - */ - public WrappingBeanBuilder<T> types(Type... types) - { - this.types = ArraysUtils.asSet(types); - return this; - } - - /** - * Add to the type closure used for bean creation. - * - * @param type additional type to use - */ - public WrappingBeanBuilder<T> addType(Type type) - { - types.add(type); - return this; - } - - /** - * Add to the type closure used for bean creation. - * - * @param types the additional types to use - */ - public WrappingBeanBuilder<T> addTypes(Type... types) - { - this.types.addAll(ArraysUtils.asSet(types)); - return this; - } - - /** - * Add to the type closure used for bean creation. - * - * @param types the additional types to use - */ - public WrappingBeanBuilder<T> addTypes(Collection<Type> types) - { - this.types.addAll(types); - return this; - } - - /** - * Qualifiers currently defined for bean creation. - * - * @return the qualifiers current defined - */ - public Set<Annotation> getQualifiers() - { - return qualifiers; - } - - /** - * Define the qualifiers used for bean creation. - * - * @param qualifiers the qualifiers to use - */ - public WrappingBeanBuilder<T> qualifiers(Set<Annotation> qualifiers) - { - this.qualifiers = qualifiers; - return this; - } - - /** - * Define the qualifiers used for bean creation. - * - * @param qualifiers the qualifiers to use - */ - public WrappingBeanBuilder<T> qualifiers(Annotation... qualifiers) - { - this.qualifiers = ArraysUtils.asSet(qualifiers); - return this; - } - - /** - * Add to the qualifiers used for bean creation. - * - * @param qualifier the additional qualifier to use - */ - public WrappingBeanBuilder<T> addQualifier(Annotation qualifier) - { - qualifiers.add(qualifier); - return this; - } - - /** - * Add to the qualifiers used for bean creation. - * - * @param qualifiers the additional qualifiers to use - */ - public WrappingBeanBuilder<T> addQualifiers(Annotation... qualifiers) - { - this.qualifiers.addAll(ArraysUtils.asSet(qualifiers)); - return this; - } - - /** - * Add to the qualifiers used for bean creation. - * - * @param qualifiers the additional qualifiers to use - */ - public WrappingBeanBuilder<T> addQualifiers( - Collection<Annotation> qualifiers) - { - this.qualifiers.addAll(qualifiers); - return this; - } - - /** - * The name of the bean currently defined for bean creation. - * - * @return the name of the bean or <code>null</code> if the bean has no name - */ - public String getName() - { - return name; - } - - /** - * Define the name of the bean used for bean creation. - * - * @param name the name of the bean to use or <code>null</code> if the bean - * should have no name - */ - public WrappingBeanBuilder<T> name(String name) - { - this.name = name; - return this; } - /** - * Scope currently defined for bean creation. - * - * @return the scope currently defined - */ - public Class<? extends Annotation> getScope() + protected void setDefaultBeanLifecycle(AnnotatedType<T> type) { - return scope; - } - - /** - * Define the scope used for bean creation. - * - * @param scope the scope to use - */ - public WrappingBeanBuilder<T> scope(Class<? extends Annotation> scope) - { - this.scope = scope; - return this; - } - - /** - * Whether the created bean will be an alternative. - * - * @return <code>true</code> if the created bean will be an alternative, - * otherwise <code>false</code> - */ - public boolean isAlternative() - { - return alternative; - } - - /** - * Define that the created bean will (or will not) be an alternative. - * - * @param alternative <code>true</code> if the created bean should be an - * alternative, otherwise <code>false</code> - */ - public WrappingBeanBuilder<T> alternative(boolean alternative) - { - this.alternative = alternative; - return this; - } - - /** - * Stereotypes currently defined for bean creation. - * - * @return the stereotypes currently defined - */ - public Set<Class<? extends Annotation>> getStereotypes() - { - return stereotypes; - } - - /** - * Define the stereotypes used for bean creation. - * - * @param stereotypes the stereotypes to use - */ - public WrappingBeanBuilder<T> stereotypes( - Set<Class<? extends Annotation>> stereotypes) - { - this.stereotypes = stereotypes; - return this; + // do nothing. We don't need that as we delegate this information } /** @@ -347,7 +62,7 @@ public class WrappingBeanBuilder<T> * * @return the bean */ - public ImmutableBeanWrapper<T> create() + public Bean<T> create() { if (isPassivationCapable()) { @@ -362,93 +77,5 @@ public class WrappingBeanBuilder<T> } } - // } - /** - * The string used when {@link #toString()} is called on the bean. - * - * @return the string currently defined - */ - public String getToString() - { - return toString; - } - - /** - * Define the string used when {@link #toString()} is called on the bean. - * - * @param toString the string to use - */ - public WrappingBeanBuilder<T> toString(String toString) - { - this.toString = toString; - return this; - } - - /** - * Whether the created bean will be nullable. - * - * @return <code>true</code> if the created bean will be nullable, otherwise - * <code>false</code> - */ - public boolean isNullable() - { - return nullable; - } - - /** - * Define that the created bean will (or will not) be nullable. - * - * @param nullable <code>true</code> if the created bean should be nullable, - * otherwise <code>false</code> - */ - public WrappingBeanBuilder<T> nullable(boolean nullable) - { - this.nullable = nullable; - return this; - } - - /** - * Whether the created bean will be passivation capable. - * - * @return <code>true</code> if the created bean will be passivation - * capable, otherwise <code>false</code> - */ - public boolean isPassivationCapable() - { - return passivationCapable; - } - - /** - * Define that the created bean will (or will not) be passivation capable. - * - * @param passivationCapable <code>true</code> if the created bean should be passivation - * capable, otherwise <code>false</code> - */ - public WrappingBeanBuilder<T> passivationCapable(boolean passivationCapable) - { - this.passivationCapable = passivationCapable; - return this; - } - - /** - * The id currently defined for bean creation. - * - * @return the id currently defined. - */ - public String getId() - { - return id; - } - - /** - * Define the id used for bean creation. - * - * @param id the id to use - */ - public WrappingBeanBuilder<T> id(String id) - { - this.id = id; - return this; - } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/metadata/InjectionPointWrapper.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/metadata/InjectionPointWrapper.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/metadata/InjectionPointWrapper.java index 390e253..1159ec6 100644 --- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/metadata/InjectionPointWrapper.java +++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/metadata/InjectionPointWrapper.java @@ -33,8 +33,8 @@ import java.util.Set; */ public class InjectionPointWrapper implements InjectionPoint { - final InjectionPoint wrapped; - final Bean<?> newBean; + private final InjectionPoint wrapped; + private final Bean<?> newBean; public InjectionPointWrapper(InjectionPoint wrapped, Bean<?> newBean) { http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java index 47db06f..b27799f 100644 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java +++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java @@ -18,42 +18,29 @@ */ package org.apache.deltaspike.core.impl.message; -import java.beans.Introspector; import java.io.Serializable; -import java.lang.annotation.Annotation; import java.lang.reflect.Method; -import java.lang.reflect.Type; +import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Set; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; -import javax.enterprise.inject.spi.AfterBeanDiscovery; -import javax.enterprise.inject.spi.AfterDeploymentValidation; -import javax.enterprise.inject.spi.AnnotatedMethod; -import javax.enterprise.inject.spi.AnnotatedType; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.BeanManager; -import javax.enterprise.inject.spi.BeforeBeanDiscovery; -import javax.enterprise.inject.spi.Extension; -import javax.enterprise.inject.spi.PassivationCapable; -import javax.enterprise.inject.spi.ProcessAnnotatedType; -import javax.enterprise.inject.spi.ProcessProducerMethod; -import javax.inject.Named; +import javax.enterprise.inject.spi.*; -import org.apache.deltaspike.core.api.literal.AnyLiteral; import org.apache.deltaspike.core.api.message.Message; import org.apache.deltaspike.core.api.message.MessageBundle; import org.apache.deltaspike.core.api.message.MessageTemplate; -import org.apache.deltaspike.core.util.bean.ImmutableBeanWrapper; -import org.apache.deltaspike.core.util.bean.ImmutablePassivationCapableBeanWrapper; -import org.apache.deltaspike.core.util.bean.WrappingBeanBuilder; +import org.apache.deltaspike.core.api.provider.BeanProvider; +import org.apache.deltaspike.core.api.provider.DependentProvider; +import org.apache.deltaspike.core.util.ClassUtils; +import org.apache.deltaspike.core.util.bean.BeanBuilder; import org.apache.deltaspike.core.spi.activation.Deactivatable; import org.apache.deltaspike.core.util.ClassDeactivationUtils; +import org.apache.deltaspike.core.util.metadata.builder.ContextualLifecycle; /** * Extension for handling {@link MessageBundle}s. @@ -64,10 +51,6 @@ import org.apache.deltaspike.core.util.ClassDeactivationUtils; public class MessageBundleExtension implements Extension, Deactivatable { private final Collection<AnnotatedType<?>> messageBundleTypes = new HashSet<AnnotatedType<?>>(); - private Bean<Object> bundleProducerBean; - private Bean<Object> namedBundleProducerBean; - private NamedTypedMessageBundle namedTypedMessageBundle = new NamedTypedMessageBundleLiteral(); - private boolean elSupportEnabled; private List<String> deploymentErrors = new ArrayList<String>(); @@ -77,7 +60,6 @@ public class MessageBundleExtension implements Extension, Deactivatable protected void init(@Observes BeforeBeanDiscovery beforeBeanDiscovery) { isActivated = ClassDeactivationUtils.isActivated(getClass()); - elSupportEnabled = ClassDeactivationUtils.isActivated(NamedMessageBundleInvocationHandler.class); } @SuppressWarnings("UnusedDeclaration") @@ -140,62 +122,6 @@ public class MessageBundleExtension implements Extension, Deactivatable return ok; } - /** - * Part of a workaround for very old CDI containers. The spec originally had a - * mismatch in the generic parameters of ProcessProducerMethod between the JavaDoc - * and the spec PDF. - * - * According to the Java EE 6 javadoc (the authority according to the powers - * that be), this is the correct order of type parameters. - * - * @see #detectProducersInverted(javax.enterprise.inject.spi.ProcessProducerMethod) - */ - @SuppressWarnings("UnusedDeclaration") - protected void detectProducers(@Observes ProcessProducerMethod<Object, TypedMessageBundleProducer> event) - { - if (!isActivated) - { - return; - } - - captureProducers(event.getAnnotatedProducerMethod(), event.getBean()); - } - - /** - * Part of a workaround for very old CDI containers. The spec originally had a - * mismatch in the generic parameters of ProcessProducerMethod between the JavaDoc - * and the spec PDF. - * - * According to the old JSR-299 spec wording, this is the correct order of type parameters. - * This is now fixed in the spec as of today, but old containers might still fire it! - * - * @see #detectProducersInverted(javax.enterprise.inject.spi.ProcessProducerMethod) - */ - @Deprecated - @SuppressWarnings("UnusedDeclaration") - protected void detectProducersInverted(@Observes ProcessProducerMethod<TypedMessageBundleProducer, Object> event) - { - if (!isActivated) - { - return; - } - - captureProducers(event.getAnnotatedProducerMethod(), event.getBean()); - } - - @SuppressWarnings("unchecked") - protected void captureProducers(AnnotatedMethod<?> method, Bean<?> bean) - { - if (method.isAnnotationPresent(TypedMessageBundle.class)) - { - bundleProducerBean = (Bean<Object>) bean; - } - else if (method.isAnnotationPresent(NamedTypedMessageBundle.class)) - { - namedBundleProducerBean = (Bean<Object>)bean; - } - } - @SuppressWarnings("UnusedDeclaration") protected void installMessageBundleProducerBeans(@Observes AfterBeanDiscovery abd, BeanManager beanManager) { @@ -208,32 +134,17 @@ public class MessageBundleExtension implements Extension, Deactivatable for (AnnotatedType<?> type : messageBundleTypes) { - abd.addBean(createMessageBundleBean(bundleProducerBean, type, beanManager)); - - if (this.elSupportEnabled) - { - Bean<?> namedBean = createNamedMessageBundleBean(namedBundleProducerBean, type, beanManager); - if (namedBean.getName() != null) - { - abd.addBean(namedBean); - } - } + abd.addBean(createMessageBundleBean(type, beanManager)); } } - private <T> Bean<T> createMessageBundleBean(Bean<Object> delegate, - AnnotatedType<T> annotatedType, + private <T> Bean<T> createMessageBundleBean(AnnotatedType<T> annotatedType, BeanManager beanManager) { - WrappingBeanBuilder<T> beanBuilder = new WrappingBeanBuilder<T>(delegate, beanManager) - .readFromType(annotatedType); + BeanBuilder<T> beanBuilder = new BeanBuilder<T>(beanManager).readFromType(annotatedType); + + beanBuilder.beanLifecycle(new MessageBundleLifecycle<T>(beanManager)); - if (this.elSupportEnabled) - { - /*see namedBundleProducerBean - a producer without injection-point is needed*/ - beanBuilder.name(null); - } - //X TODO re-visit type.getBaseType() in combination with #addQualifier beanBuilder.types(annotatedType.getJavaClass(), Object.class, Serializable.class); beanBuilder.passivationCapable(true); beanBuilder.id("MessageBundleBean#" + annotatedType.getJavaClass().getName()); @@ -241,105 +152,42 @@ public class MessageBundleExtension implements Extension, Deactivatable return beanBuilder.create(); } - private <T> Bean<T> createNamedMessageBundleBean(Bean<Object> delegate, - AnnotatedType<T> annotatedType, - BeanManager beanManager) + @SuppressWarnings("UnusedDeclaration") + protected void cleanup(@Observes AfterDeploymentValidation afterDeploymentValidation) { - WrappingBeanBuilder<T> beanBuilder = new WrappingBeanBuilder<T>(delegate, beanManager) { - @Override - public ImmutableBeanWrapper<T> create() - { - final ImmutableBeanWrapper<T> result = super.create(); - - String beanName = createBeanName(result.getTypes()); - - Set<Annotation> qualifiers = new HashSet<Annotation>(); - qualifiers.add(new AnyLiteral()); - qualifiers.add(namedTypedMessageBundle); - - if (isPassivationCapable()) - { - return new ImmutablePassivationCapableBeanWrapper<T>(result, - beanName, qualifiers, result.getScope(), - result.getStereotypes(), result.getTypes(), result.isAlternative(), - result.isNullable(), result.toString(), ((PassivationCapable)result).getId()) { - @Override - public T create(CreationalContext<T> creationalContext) - { - MessageBundleContext.setBean(result); + messageBundleTypes.clear(); + } - try - { - return super.create(creationalContext); - } - finally - { - MessageBundleContext.reset(); - } - } - }; - } - else - { - return new ImmutableBeanWrapper<T>(result, - beanName, qualifiers, result.getScope(), - result.getStereotypes(), result.getTypes(), result.isAlternative(), - result.isNullable(), result.toString()) { - @Override - public T create(CreationalContext<T> creationalContext) - { - MessageBundleContext.setBean(result); - try - { - return super.create(creationalContext); - } - finally - { - MessageBundleContext.reset(); - } - } - }; - } - } + private static class MessageBundleLifecycle<T> implements ContextualLifecycle<T> + { + private final BeanManager beanManager; - private String createBeanName(Set<Type> types) - { - for (Object type : types) - { - if (type instanceof Class) - { - Named namedAnnotation = ((Class<?>) type).getAnnotation(Named.class); + private DependentProvider<MessageBundleInvocationHandler> invocationHandlerProvider; - if (namedAnnotation == null) - { - continue; - } + private MessageBundleLifecycle(BeanManager beanManager) + { + this.beanManager = beanManager; + } - String result = namedAnnotation.value(); - if (!"".equals(result)) - { - return result; - } - return Introspector.decapitalize(((Class<?>) type).getSimpleName()); - } - } - return null; - } - }; - beanBuilder.readFromType(annotatedType); + @Override + public T create(Bean<T> bean, CreationalContext<T> creationalContext) + { + invocationHandlerProvider = BeanProvider.getDependent(beanManager, MessageBundleInvocationHandler.class); - //X TODO re-visit type.getBaseType() in combination with #addQualifier - beanBuilder.types(annotatedType.getJavaClass(), Object.class, Serializable.class); - beanBuilder.passivationCapable(true); - beanBuilder.id("NamedMessageBundleBean#" + annotatedType.getJavaClass().getName()); + return createMessageBundleProxy((Class<T>) bean.getBeanClass(), invocationHandlerProvider.get()); + } - return beanBuilder.create(); - } + @Override + public void destroy(Bean<T> bean, T instance, CreationalContext<T> creationalContext) + { + invocationHandlerProvider.destroy(); + } + private <T> T createMessageBundleProxy(Class<T> type, MessageBundleInvocationHandler handler) + { + return type.cast(Proxy.newProxyInstance(ClassUtils.getClassLoader(null), + new Class<?>[]{type}, handler)); + } - @SuppressWarnings("UnusedDeclaration") - protected void cleanup(@Observes AfterDeploymentValidation afterDeploymentValidation) - { - messageBundleTypes.clear(); } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedMessageBundleInvocationHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedMessageBundleInvocationHandler.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedMessageBundleInvocationHandler.java deleted file mode 100644 index b2eec81..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedMessageBundleInvocationHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.deltaspike.core.impl.message; - -import org.apache.deltaspike.core.spi.activation.Deactivatable; - -import javax.enterprise.context.Dependent; -import javax.enterprise.inject.Typed; -import java.lang.reflect.Method; - -@Dependent -@Typed(NamedMessageBundleInvocationHandler.class) -public class NamedMessageBundleInvocationHandler extends MessageBundleInvocationHandler implements Deactivatable -{ - private static final long serialVersionUID = -7089857581799104783L; - - private Class<?> targetType; - - @Override - public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable - { - int argCount = 0; - boolean nullValueFound = false; - String methodName = new RuntimeException().getStackTrace()[1].getMethodName(); - - if (args != null) - { - argCount = args.length; - } - - Class<?>[] paramTypes = new Class[argCount]; - - for (int i = 0; i < argCount; i++) - { - if (args[i] != null) - { - paramTypes[i] = args[i].getClass(); - } - else - { - nullValueFound = true; - } - } - - Method targetMethod = null; - - if (!nullValueFound) - { - targetMethod = this.targetType.getMethod(methodName, paramTypes); - } - else - { - //TODO improve it - for (Method currentMethod : this.targetType.getDeclaredMethods()) - { - if (currentMethod.getParameterTypes().length == argCount && currentMethod.getName().equals(methodName)) - { - if (targetMethod != null) - { - throw new IllegalStateException("Two methods with the same name and parameter-count found. " + - "It isn't possible to select the correct one, because one argument is 'null'."); - } - targetMethod = currentMethod; - } - } - } - - if (targetMethod == null) - { - throw new IllegalStateException(methodName + " can't be found on " + this.targetType); - } - - return super.invoke(proxy, targetMethod, args); - } - - public void setTargetType(Class<?> targetType) - { - this.targetType = targetType; - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundle.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundle.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundle.java deleted file mode 100644 index d7b2524..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundle.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.deltaspike.core.impl.message; - -import javax.inject.Qualifier; -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Internal-qualifier used to identify the named typed message bundle producer - */ -@Qualifier -@Target({ TYPE, METHOD, PARAMETER, FIELD }) -@Retention(RUNTIME) -@Documented -@interface NamedTypedMessageBundle -{ -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundleLiteral.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundleLiteral.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundleLiteral.java deleted file mode 100644 index 3ef8606..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NamedTypedMessageBundleLiteral.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.deltaspike.core.impl.message; - -import javax.enterprise.util.AnnotationLiteral; - -class NamedTypedMessageBundleLiteral - extends AnnotationLiteral<NamedTypedMessageBundle> implements NamedTypedMessageBundle -{ - private static final long serialVersionUID = -8841990503456285744L; -} - http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java deleted file mode 100644 index 5324697..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.deltaspike.core.impl.message; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import javax.inject.Qualifier; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -/** - * Internal-qualifier used to identify the typed message bundle producer for the - * wrapping bean. - */ -@Qualifier -@Target({ TYPE, METHOD, PARAMETER, FIELD }) -@Retention(RUNTIME) -@Documented -@interface TypedMessageBundle -{ - -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java ---------------------------------------------------------------------- diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java deleted file mode 100644 index 5e33d94..0000000 --- a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.deltaspike.core.impl.message; - - -import java.io.Serializable; -import java.lang.reflect.Proxy; - -import javax.enterprise.context.Dependent; -import javax.enterprise.inject.Produces; -import javax.enterprise.inject.spi.Bean; -import javax.enterprise.inject.spi.InjectionPoint; - -import org.apache.deltaspike.core.util.ClassUtils; -import org.apache.deltaspike.core.util.ReflectionUtils; - -/** - * The <code>TypedMessageBundleProducer</code> provides a producer method for - * injected typed message bundles. - */ -public class TypedMessageBundleProducer implements Serializable -{ - private static final long serialVersionUID = -5077306523543940760L; - private static final String JAVA_PACKAGE = "java."; - - @Produces - @Dependent - @TypedMessageBundle - @SuppressWarnings("UnusedDeclaration") - Object produceTypedMessageBundle(InjectionPoint injectionPoint, MessageBundleInvocationHandler handler) - { - return createMessageBundleProxy(ReflectionUtils.getRawType(injectionPoint.getType()), handler); - } - - @Produces - @Dependent - @NamedTypedMessageBundle - @SuppressWarnings("UnusedDeclaration") - Object produceTypedMessageBundle(NamedMessageBundleInvocationHandler handler) - { - Bean currentMessageBundleContextBean = MessageBundleContext.getCurrentMessageBundleBean(); - Class<?> type = extractCustomType(currentMessageBundleContextBean); - handler.setTargetType(type); - return createMessageBundleProxy(type, handler); - } - - private Class<?> extractCustomType(Bean currentMessageBundleBean) - { - for (Object type : currentMessageBundleBean.getTypes()) - { - if (type instanceof Class && !((Class)type).getName().startsWith(JAVA_PACKAGE)) - { - return (Class)type; - } - } - throw new IllegalStateException("no custom type found for bean: " + currentMessageBundleBean.toString()); - } - - private <T> T createMessageBundleProxy(Class<T> type, MessageBundleInvocationHandler handler) - { - return type.cast(Proxy.newProxyInstance(ClassUtils.getClassLoader(null), - new Class<?>[]{type}, handler)); - } -} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/JsfMessageTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/JsfMessageTest.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/JsfMessageTest.java index dfc8ac0..b7c8913 100644 --- a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/JsfMessageTest.java +++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/JsfMessageTest.java @@ -103,6 +103,12 @@ public class JsfMessageTest // check the free message usage Assert.assertTrue(ExpectedConditions.textToBePresentInElement( By.id("test:valueOutput"), "a simple message without a param.").apply(driver)); + + // and also the usage via direct EL invocation + Assert.assertTrue(ExpectedConditions.textToBePresentInElement( + By.id("test:elOutput"), "a simple message without a param.").apply(driver)); + Assert.assertTrue(ExpectedConditions.textToBePresentInElement( + By.id("test:elOutputWithParam"), "simple message with a string param hiho.").apply(driver)); } @Test http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/beans/UserMessage.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/beans/UserMessage.java b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/beans/UserMessage.java index 4e7b23b..187be4b 100644 --- a/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/beans/UserMessage.java +++ b/deltaspike/modules/jsf/impl/src/test/java/org/apache/deltaspike/test/jsf/impl/message/beans/UserMessage.java @@ -22,7 +22,10 @@ import org.apache.deltaspike.core.api.message.Message; import org.apache.deltaspike.core.api.message.MessageBundle; import org.apache.deltaspike.core.api.message.MessageContextConfig; +import javax.inject.Named; + @MessageBundle +@Named @MessageContextConfig(messageSource = "jsfMessageTest.UserMessage") public interface UserMessage { http://git-wip-us.apache.org/repos/asf/deltaspike/blob/7ad36c14/deltaspike/modules/jsf/impl/src/test/resources/jsfMessageTest/page.xhtml ---------------------------------------------------------------------- diff --git a/deltaspike/modules/jsf/impl/src/test/resources/jsfMessageTest/page.xhtml b/deltaspike/modules/jsf/impl/src/test/resources/jsfMessageTest/page.xhtml index 4137cc7..f7e4e0b 100644 --- a/deltaspike/modules/jsf/impl/src/test/resources/jsfMessageTest/page.xhtml +++ b/deltaspike/modules/jsf/impl/src/test/resources/jsfMessageTest/page.xhtml @@ -41,6 +41,16 @@ <h:outputText id="valueOutput" value="#{jsfMessageBackingBean.someMessage}"/> <br/> + <br/> + <h:outputLabel for="elOutput" value="and via EL:"/> + <h:outputText id="elOutput" value="#{userMessage.simpleMessageNoParam()}"/> + <br/> + + <br/> + <h:outputLabel for="elOutputWithParam" value="and via EL and param:"/> + <h:outputText id="elOutputWithParam" value="#{userMessage.simpleMessageWithParam('hiho')}"/> + <br/> + </h:form> </div> </f:view>
