You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by ke...@apache.org on 2012/04/05 16:35:34 UTC
[3/3] git commit: DELTASPIKE-146: Submitted on behalf of a
third-party: Red Hat, Inc. under the terms of the ALv2
DELTASPIKE-146: Submitted on behalf of a third-party: Red Hat, Inc. under the terms of the ALv2
Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/11f95389
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/11f95389
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/11f95389
Branch: refs/heads/master
Commit: 11f953895eeec2d321e7ffefe7eb4a4a590dbfd7
Parents: 3fe012a
Author: Ken Finnigan <ke...@kenfinnigan.me>
Authored: Thu Apr 5 09:47:46 2012 -0400
Committer: Ken Finnigan <ke...@kenfinnigan.me>
Committed: Thu Apr 5 09:53:38 2012 -0400
----------------------------------------------------------------------
.../core/api/literal/MessageBundleLiteral.java | 32 +
.../apache/deltaspike/core/api/message/Cause.java | 40 ++
.../deltaspike/core/api/message/Message.java | 68 ++
.../deltaspike/core/api/message/MessageBundle.java | 40 ++
.../core/impl/message/AbstractImmutableBean.java | 219 +++++++
.../deltaspike/core/impl/message/Arrays2.java | 54 ++
.../core/impl/message/ImmutableNarrowingBean.java | 128 ++++
.../core/impl/message/MessageBundleExtension.java | 108 ++++
.../message/MessageBundleInvocationHandler.java | 121 ++++
.../core/impl/message/MessageFactory.java | 51 ++
.../core/impl/message/NarrowingBeanBuilder.java | 480 +++++++++++++++
.../core/impl/message/TypedMessageBundle.java | 44 ++
.../impl/message/TypedMessageBundleProducer.java | 44 ++
.../services/javax.enterprise.inject.spi.Extension | 3 +-
.../test/core/api/message/BirdMessages.java | 28 +
.../deltaspike/test/core/api/message/Jay.java | 35 +
.../test/core/api/message/MessageTest.java | 81 +++
17 files changed, 1575 insertions(+), 1 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java
new file mode 100644
index 0000000..03b73bc
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/literal/MessageBundleLiteral.java
@@ -0,0 +1,32 @@
+/*
+ * 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.api.literal;
+
+import javax.enterprise.util.AnnotationLiteral;
+
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+/**
+ * Literal for {@link MessageBundle}
+ */
+public class MessageBundleLiteral extends AnnotationLiteral<MessageBundle>
+ implements MessageBundle
+{
+ private static final long serialVersionUID = 5116646785333766333L;
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
new file mode 100644
index 0000000..de23600
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Cause.java
@@ -0,0 +1,40 @@
+/*
+ * 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.api.message;
+
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Mark a parameter as being the "exception cause" parameter rather than a
+ * positional format parameter.
+ *
+ * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
+ */
+@Retention(CLASS)
+@Target(PARAMETER)
+@Documented
+public @interface Cause
+{
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
new file mode 100644
index 0000000..fac3dda
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/Message.java
@@ -0,0 +1,68 @@
+/*
+ * 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.api.message;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+@Target(METHOD)
+@Retention(RUNTIME)
+@Documented
+public @interface Message
+{
+
+ /**
+ * The default format string of this message.
+ *
+ * @return the format string
+ */
+ String value();
+
+ /**
+ * The format type of this method (defaults to {@link Format#PRINTF}).
+ *
+ * @return the format type
+ */
+ Format format() default Format.PRINTF;
+
+ /**
+ * The possible format types.
+ */
+ enum Format
+ {
+
+ /**
+ * A {@link java.util.Formatter}-type format string.
+ */
+ PRINTF,
+ /**
+ * A {@link java.text.MessageFormat}-type format string.
+ */
+ MESSAGE_FORMAT,
+ /**
+ * An expression language type format string.
+ */
+ EXP_LANG
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
new file mode 100644
index 0000000..96c50f7
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/message/MessageBundle.java
@@ -0,0 +1,40 @@
+/*
+ * 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.api.message;
+
+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;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Qualifier
+@Documented
+public @interface MessageBundle
+{
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
new file mode 100644
index 0000000..58d1875
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/AbstractImmutableBean.java
@@ -0,0 +1,219 @@
+/*
+ * 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.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.deltaspike.core.api.literal.DefaultLiteral;
+
+/**
+ * <p>
+ * A base class for implementing {@link Bean}. The attributes are immutable, and
+ * collections are defensively copied on instantiation. It uses the defaults
+ * from the specification for properties if not specified.
+ * </p>
+ * <p/>
+ * <p>
+ * This class does not provide any bean lifecycle operations
+ * </p>
+ *
+ * @see ImmutableBean
+ * @see ImmutableNarrowingBean
+ */
+abstract class AbstractImmutableBean<T> implements Bean<T>
+{
+ private transient Logger log = Logger.getLogger(AbstractImmutableBean.class
+ .getName());
+
+ private final Class<?> beanClass;
+ private final String name;
+ private final Set<Annotation> qualifiers;
+ private final Class<? extends Annotation> scope;
+ private final Set<Class<? extends Annotation>> stereotypes;
+ private final Set<Type> types;
+ private final boolean alternative;
+ private final boolean nullable;
+ private final Set<InjectionPoint> injectionPoints;
+ private final String toString;
+
+ /**
+ * Create a new, immutable bean. All arguments passed as collections are
+ * defensively copied.
+ *
+ * @param beanClass
+ * The Bean class, may not be null
+ * @param name
+ * The bean name
+ * @param qualifiers
+ * The bean's qualifiers, if null, a singleton set of
+ * {@link Default} is used
+ * @param scope
+ * The bean's scope, if null, the default scope of
+ * {@link Dependent} is used
+ * @param stereotypes
+ * The bean's stereotypes, if null, an empty set is used
+ * @param types
+ * The bean's types, if null, the beanClass and {@link Object}
+ * will be used
+ * @param alternative
+ * True if the bean is an alternative
+ * @param nullable
+ * True if the bean is nullable
+ * @param injectionPoints
+ * the bean's injection points, if null an empty set is used
+ * @param beanLifecycle
+ * Handler for {@link #create(CreationalContext)} and
+ * {@link #destroy(Object, CreationalContext)}
+ * @throws IllegalArgumentException
+ * if the beanClass is null
+ */
+ public AbstractImmutableBean(Class<?> beanClass, String name,
+ Set<Annotation> qualifiers, Class<? extends Annotation> scope,
+ Set<Class<? extends Annotation>> stereotypes, Set<Type> types,
+ boolean alternative, boolean nullable,
+ Set<InjectionPoint> injectionPoints, String toString)
+ {
+ if (beanClass == null)
+ {
+ throw new IllegalArgumentException("beanClass cannot be null");
+ }
+ this.beanClass = beanClass;
+ this.name = name;
+ if (qualifiers == null)
+ {
+ this.qualifiers = Collections
+ .<Annotation> singleton(new DefaultLiteral());
+ log.finest("No qualifers provided for bean class " + beanClass
+ + ", using singleton set of @Default");
+ }
+ else
+ {
+ this.qualifiers = new HashSet<Annotation>(qualifiers);
+ }
+ if (scope == null)
+ {
+ this.scope = Dependent.class;
+ log.finest("No scope provided for bean class " + beanClass
+ + ", using @Dependent");
+ }
+ else
+ {
+ this.scope = scope;
+ }
+ if (stereotypes == null)
+ {
+ this.stereotypes = Collections.emptySet();
+ }
+ else
+ {
+ this.stereotypes = new HashSet<Class<? extends Annotation>>(
+ stereotypes);
+ }
+ if (types == null)
+ {
+ this.types = Arrays2.<Type> asSet(Object.class, beanClass);
+ log.finest("No types provided for bean class " + beanClass
+ + ", using [java.lang.Object.class, " + beanClass.getName()
+ + ".class]");
+ }
+ else
+ {
+ this.types = new HashSet<Type>(types);
+ }
+ if (injectionPoints == null)
+ {
+ this.injectionPoints = Collections.emptySet();
+ }
+ else
+ {
+ this.injectionPoints = new HashSet<InjectionPoint>(injectionPoints);
+ }
+ this.alternative = alternative;
+ this.nullable = nullable;
+ if (toString != null)
+ {
+ this.toString = toString;
+ }
+ else
+ {
+ this.toString = "Custom Bean with bean class " + beanClass
+ + " and qualifiers " + qualifiers;
+ }
+ }
+
+ public Class<?> getBeanClass()
+ {
+ return beanClass;
+ }
+
+ public Set<InjectionPoint> getInjectionPoints()
+ {
+ return injectionPoints;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public Set<Annotation> getQualifiers()
+ {
+ return Collections.unmodifiableSet(qualifiers);
+ }
+
+ public Class<? extends Annotation> getScope()
+ {
+ return scope;
+ }
+
+ public Set<Class<? extends Annotation>> getStereotypes()
+ {
+ return Collections.unmodifiableSet(stereotypes);
+ }
+
+ public Set<Type> getTypes()
+ {
+ return Collections.unmodifiableSet(types);
+ }
+
+ public boolean isAlternative()
+ {
+ return alternative;
+ }
+
+ public boolean isNullable()
+ {
+ return nullable;
+ }
+
+ @Override
+ public String toString()
+ {
+ return toString;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java
new file mode 100644
index 0000000..2c8a715
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/Arrays2.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util.HashSet;
+import java.util.Set;
+
+/**
+ * A collection of utilities for working with Arrays that goes beyond that in
+ * the JDK.
+ */
+class Arrays2
+{
+
+ private Arrays2()
+ {
+ }
+
+ /**
+ * Create a set from an array. If the array contains duplicate objects, the
+ * last object in the array will be placed in resultant set.
+ *
+ * @param <T>
+ * the type of the objects in the set
+ * @param array
+ * the array from which to create the set
+ * @return the created sets
+ */
+ public static <T> Set<T> asSet(T... array)
+ {
+ Set<T> result = new HashSet<T>();
+ for (T a : array)
+ {
+ result.add(a);
+ }
+ return result;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
new file mode 100644
index 0000000..0c7fdc5
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/ImmutableNarrowingBean.java
@@ -0,0 +1,128 @@
+/*
+ * 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.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+
+import org.apache.deltaspike.core.util.Reflections;
+
+/**
+ * <p>
+ * A narrowing bean allows you to build a general purpose bean (likely a
+ * producer method), and register it for a narrowed type (or qualifiers). For
+ * example, you could create a producer method which uses an a String ID to
+ * located an object (the object can have any class):
+ * </p>
+ * <p/>
+ *
+ * <pre>
+ * @Produces
+ * // Use some synthetic scope to prevent this from interfering with other
+ * // resolutions
+ * @MyProducer
+ * Object produce(InjectionPoint ip)
+ * {
+ * String id = ip.getAnnotated().getAnnotation(Id.class).value();
+ * // Lookup and return the object for the id
+ * }
+ * </pre>
+ * <p/>
+ * <p>
+ * The delegate bean <em>must</em> return an object which can be cast to the
+ * type <code>T</code>, otherwise a {@link ClassCastException} will be thrown at
+ * runtime when the bean is created.
+ * </p>
+ * <p/>
+ * <p>
+ * You can then register a narrowing bean for each type you need:
+ * </p>
+ * <p/>
+ *
+ * <pre>
+ * event.addBean(new NarrowingBeanBuilder<T>(delegateBean).readFromType(type)
+ * .create());
+ * </pre>
+ * <p/>
+ * <p>
+ * {@link ImmutableNarrowingBean} will use the annotations on
+ * <code>defininingType</code> to discover the qualifiers, types, scope,
+ * stereotypes of the bean, as well as determine it's name (if any) and whether
+ * it is an alternative.
+ * </p>
+ * <p/>
+ * <p>
+ * The attributes are immutable, and collections are defensively copied on
+ * instantiation. It uses the defaults from the specification for properties if
+ * not specified.
+ * </p>
+ *
+ * @see NarrowingBeanBuilder
+ * @see ImmutablePassivationCapableNarrowingBean
+ */
+class ImmutableNarrowingBean<T> extends AbstractImmutableBean<T>
+{
+
+ private final Bean<Object> delegate;
+
+ /**
+ * Instantiate a new {@link ImmutableNarrowingBean}.
+ *
+ * @param delegate
+ * the bean to delegate the lifecycle to
+ * @param name
+ * the name of the bean
+ * @param qualifiers
+ * the qualifiers of the bean
+ * @param scope
+ * the scope of the bean
+ * @param stereotypes
+ * the bean's stereotypes
+ * @param types
+ * the types of the bean
+ * @param alternative
+ * whether the bean is an alternative
+ */
+ public ImmutableNarrowingBean(Bean<Object> delegate, String name,
+ Set<Annotation> qualifiers, Class<? extends Annotation> scope,
+ Set<Class<? extends Annotation>> stereotypes, Set<Type> types,
+ boolean alternative, boolean nullable, String toString)
+ {
+ super(delegate.getBeanClass(), name, qualifiers, scope, stereotypes,
+ types, alternative, nullable, delegate.getInjectionPoints(),
+ toString);
+ this.delegate = delegate;
+ }
+
+ public T create(CreationalContext<T> creationalContext)
+ {
+ return Reflections.<T> cast(delegate.create(Reflections
+ .<CreationalContext<Object>> cast(creationalContext)));
+ }
+
+ public void destroy(T instance, CreationalContext<T> creationalContext)
+ {
+ delegate.destroy(instance,
+ Reflections.<CreationalContext<Object>> cast(creationalContext));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..a992c89
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleExtension.java
@@ -0,0 +1,108 @@
+/*
+ * 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.util.Collection;
+import java.util.HashSet;
+
+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.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessProducerMethod;
+
+import org.apache.deltaspike.core.api.literal.MessageBundleLiteral;
+import org.apache.deltaspike.core.api.message.MessageBundle;
+import org.apache.deltaspike.core.spi.activation.Deactivatable;
+
+public class MessageBundleExtension implements Extension, Deactivatable
+{
+ private final Collection<AnnotatedType<?>> messageBundleTypes;
+ private Bean<Object> bundleProducerBean;
+
+ public MessageBundleExtension()
+ {
+ this.messageBundleTypes = new HashSet<AnnotatedType<?>>();
+ }
+
+ void detectInterfaces(@Observes ProcessAnnotatedType<?> event,
+ BeanManager beanManager)
+ {
+ AnnotatedType<?> type = event.getAnnotatedType();
+ if (type.isAnnotationPresent(MessageBundle.class))
+ {
+ messageBundleTypes.add(type);
+ }
+ }
+
+ // according to the Java EE 6 javadoc (the authority according to the powers
+ // that be),
+ // this is the correct order of type parameters
+ void detectProducers(
+ @Observes ProcessProducerMethod<Object, TypedMessageBundleProducer> event)
+ {
+ captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
+ }
+
+ // according to JSR-299 spec, this is the correct order of type parameters
+ @Deprecated
+ void detectProducersInverted(
+ @Observes ProcessProducerMethod<TypedMessageBundleProducer, Object> event)
+ {
+ captureProducers(event.getAnnotatedProducerMethod(), event.getBean());
+ }
+
+ @SuppressWarnings("unchecked")
+ void captureProducers(AnnotatedMethod<?> method, Bean<?> bean)
+ {
+ if (method.isAnnotationPresent(TypedMessageBundle.class))
+ {
+ this.bundleProducerBean = (Bean<Object>) bean;
+ }
+ }
+
+ void installBeans(@Observes AfterBeanDiscovery event,
+ BeanManager beanManager)
+ {
+ for (AnnotatedType<?> type : messageBundleTypes)
+ {
+ event.addBean(createMessageBundleBean(bundleProducerBean, type,
+ beanManager));
+ }
+ }
+
+ private static <T> Bean<T> createMessageBundleBean(Bean<Object> delegate,
+ AnnotatedType<T> type, BeanManager beanManager)
+ {
+ return new NarrowingBeanBuilder<T>(delegate, beanManager)
+ .types(type.getBaseType(), Object.class)
+ .addQualifier(new MessageBundleLiteral()).create();
+ }
+
+ void cleanup(@Observes AfterDeploymentValidation event)
+ {
+ this.messageBundleTypes.clear();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
new file mode 100644
index 0000000..ca99a17
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageBundleInvocationHandler.java
@@ -0,0 +1,121 @@
+/*
+ * 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.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.deltaspike.core.api.message.Cause;
+import org.apache.deltaspike.core.api.message.Message;
+
+class MessageBundleInvocationHandler implements InvocationHandler
+{
+
+ /**
+ * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
+ * java.lang.reflect.Method, java.lang.Object[])
+ */
+ @Override
+ public Object invoke(final Object proxy, final Method method,
+ final Object[] args) throws Throwable
+ {
+ final Message message = method.getAnnotation(Message.class);
+ if (message == null)
+ {
+ // nothing to do...
+ return null;
+ }
+ final Annotation[][] parameterAnnotations = method
+ .getParameterAnnotations();
+ ArrayList<Object> newArgs = new ArrayList<Object>();
+ Throwable cause = extractCause(parameterAnnotations, args, newArgs);
+ String result;
+ switch (message.format())
+ {
+ case PRINTF:
+ {
+ result = String.format(message.value(), newArgs.toArray());
+ break;
+ }
+ case MESSAGE_FORMAT:
+ {
+ result = MessageFormat.format(message.value(),
+ newArgs.toArray());
+ break;
+ }
+ default:
+ throw new IllegalStateException();
+ }
+ final Class<?> returnType = method.getReturnType();
+ if (Throwable.class.isAssignableFrom(returnType))
+ {
+ // the return type is an exception
+ if (cause != null)
+ {
+ final Constructor<?> constructor = returnType.getConstructor(
+ String.class, Throwable.class);
+ return constructor.newInstance(result, cause);
+ }
+ else
+ {
+ final Constructor<?> constructor = returnType
+ .getConstructor(String.class);
+ return constructor.newInstance(result);
+ }
+ }
+ else
+ {
+ return result;
+ }
+ }
+
+ protected static Throwable extractCause(
+ final Annotation[][] parameterAnnotations, final Object[] args,
+ final List<Object> newArgs)
+ {
+ Throwable cause = null;
+ for (int i = 0; i < parameterAnnotations.length; i++)
+ {
+ Annotation[] annotations = parameterAnnotations[i];
+ boolean found = false;
+ for (Annotation annotation : annotations)
+ {
+ if (annotation instanceof Cause)
+ {
+ if (cause == null)
+ {
+ cause = (Throwable) args[i];
+ }
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ newArgs.add(args[i]);
+ }
+ }
+ return cause;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
new file mode 100644
index 0000000..a966317
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/MessageFactory.java
@@ -0,0 +1,51 @@
+/*
+ * 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.reflect.Proxy;
+
+/**
+ * A factory class to produce message bundle implementations.
+ */
+final class MessageFactory
+{
+
+ private MessageFactory()
+ {
+ }
+
+ /**
+ * Get a message bundle of the given type. Equivalent to
+ * <code>{@link #getBundle(Class, java.util.Locale) getBundle}(type, Locale.getDefault())</code>
+ * .
+ *
+ * @param type
+ * the bundle type class
+ * @param <T>
+ * the bundle type
+ * @return the bundle
+ */
+ public static <T> T getBundle(Class<T> type)
+ {
+ return type.cast(Proxy.newProxyInstance(type.getClassLoader(),
+ new Class<?>[]
+ { type }, new MessageBundleInvocationHandler()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
new file mode 100644
index 0000000..49096a4
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/NarrowingBeanBuilder.java
@@ -0,0 +1,480 @@
+/*
+ * 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 static org.apache.deltaspike.core.impl.message.Arrays2.asSet;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+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 org.apache.deltaspike.core.api.literal.AnyLiteral;
+import org.apache.deltaspike.core.api.literal.DefaultLiteral;
+
+/**
+ * Builder for {@link ImmutableNarrowingBean} and
+ * {@link ImmutablePassivationCapableNarrowingBean}.
+ *
+ * @see ImmutableNarrowingBean
+ * @see ImmutablePassivationCapableNarrowingBean
+ */
+class NarrowingBeanBuilder<T>
+{
+ private final Bean<Object> 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 NarrowingBeanBuilder}.
+ *
+ * @param delegate
+ * the delegate bean
+ */
+ public NarrowingBeanBuilder(Bean<Object> delegate, BeanManager beanManager)
+ {
+ this.delegate = delegate;
+ this.beanManager = beanManager;
+ }
+
+ /**
+ * Create a new {@link NarrowingBeanBuilder}, allowing Java to infer the
+ * type <code>T</code>.
+ *
+ * @param <T>
+ * the type of the bean
+ * @param delegate
+ * the delegate bean
+ */
+ public static <T> NarrowingBeanBuilder<T> of(Bean<Object> delegate,
+ BeanManager beanManager)
+ {
+ return new NarrowingBeanBuilder<T>(delegate, beanManager);
+ }
+
+ /**
+ * <p>
+ * Read the {@link AnnotatedType}, creating a narrowing bean from the class
+ * and its annotations.
+ * </p>
+ *
+ * @param type
+ * the type to read
+ */
+ public NarrowingBeanBuilder<T> readFromType(AnnotatedType<T> type)
+ {
+ this.types = new HashSet<Type>(type.getTypeClosure());
+ this.qualifiers = new HashSet<Annotation>();
+ this.stereotypes = new HashSet<Class<? extends Annotation>>();
+ String name = null;
+ Class<? extends Annotation> scope = Dependent.class;
+ for (Annotation annotation : type.getAnnotations())
+ {
+ if (beanManager.isQualifier(annotation.annotationType()))
+ {
+ this.qualifiers.add(annotation);
+ }
+ else if (annotation.annotationType().equals(Named.class))
+ {
+ name = Named.class.cast(annotation).value();
+ }
+ else if (beanManager.isScope(annotation.annotationType()))
+ {
+ scope = annotation.annotationType();
+ }
+ else if (beanManager.isStereotype(annotation.annotationType()))
+ {
+ this.stereotypes.add(annotation.annotationType());
+ }
+ }
+ if (qualifiers.isEmpty())
+ {
+ this.qualifiers.add(new DefaultLiteral());
+ }
+ this.qualifiers.add(new AnyLiteral());
+ this.name = "".equals(name) ? null : name;
+ this.scope = scope;
+ this.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 NarrowingBeanBuilder<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 NarrowingBeanBuilder<T> types(Type... types)
+ {
+ this.types = asSet(types);
+ return this;
+ }
+
+ /**
+ * Add to the type closure used for bean creation.
+ *
+ * @param type
+ * additional type to use
+ */
+ public NarrowingBeanBuilder<T> addType(Type type)
+ {
+ this.types.add(type);
+ return this;
+ }
+
+ /**
+ * Add to the type closure used for bean creation.
+ *
+ * @param types
+ * the additional types to use
+ */
+ public NarrowingBeanBuilder<T> addTypes(Type... types)
+ {
+ this.types.addAll(asSet(types));
+ return this;
+ }
+
+ /**
+ * Add to the type closure used for bean creation.
+ *
+ * @param types
+ * the additional types to use
+ */
+ public NarrowingBeanBuilder<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 NarrowingBeanBuilder<T> qualifiers(Set<Annotation> qualifiers)
+ {
+ this.qualifiers = qualifiers;
+ return this;
+ }
+
+ /**
+ * Define the qualifiers used for bean creation.
+ *
+ * @param qualifiers
+ * the qualifiers to use
+ */
+ public NarrowingBeanBuilder<T> qualifiers(Annotation... qualifiers)
+ {
+ this.qualifiers = asSet(qualifiers);
+ return this;
+ }
+
+ /**
+ * Add to the qualifiers used for bean creation.
+ *
+ * @param qualifiers
+ * the additional qualifier to use
+ */
+ public NarrowingBeanBuilder<T> addQualifier(Annotation qualifier)
+ {
+ this.qualifiers.add(qualifier);
+ return this;
+ }
+
+ /**
+ * Add to the qualifiers used for bean creation.
+ *
+ * @param qualifiers
+ * the additional qualifiers to use
+ */
+ public NarrowingBeanBuilder<T> addQualifiers(Annotation... qualifiers)
+ {
+ this.qualifiers.addAll(asSet(qualifiers));
+ return this;
+ }
+
+ /**
+ * Add to the qualifiers used for bean creation.
+ *
+ * @param qualifiers
+ * the additional qualifiers to use
+ */
+ public NarrowingBeanBuilder<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 NarrowingBeanBuilder<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()
+ {
+ return scope;
+ }
+
+ /**
+ * Define the scope used for bean creation.
+ *
+ * @param scope
+ * the scope to use
+ */
+ public NarrowingBeanBuilder<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 NarrowingBeanBuilder<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 NarrowingBeanBuilder<T> stereotypes(
+ Set<Class<? extends Annotation>> stereotypes)
+ {
+ this.stereotypes = stereotypes;
+ return this;
+ }
+
+ /**
+ * <p>
+ * Use the bean builder's current state to define the bean.
+ * </p>
+ *
+ * @return the bean
+ */
+ public ImmutableNarrowingBean<T> create()
+ {
+ // Commented out due to it not being required for initial Message
+ // implementation
+ // if (isPassivationCapable()) {
+ // return new ImmutablePassivationCapableNarrowingBean<T>(delegate,
+ // name, qualifiers, scope, stereotypes, types, alternative,
+ // nullable, toString, id);
+ // } else {
+ return new ImmutableNarrowingBean<T>(delegate, name, qualifiers, scope,
+ stereotypes, types, alternative, nullable, toString);
+ }
+
+ // }
+
+ /**
+ * 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 NarrowingBeanBuilder<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 NarrowingBeanBuilder<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 nullable
+ * <code>true</code> if the created bean should be passivation
+ * capable, otherwise <code>false</code>
+ */
+ public NarrowingBeanBuilder<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 NarrowingBeanBuilder<T> id(String id)
+ {
+ this.id = id;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..03996ec
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundle.java
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+@Qualifier
+@Target({ TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+/**
+ * Internal-qualifier used to identify the typed message bundle producer for the
+ * wrapping bean.
+ */
+@interface TypedMessageBundle
+{
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/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
new file mode 100644
index 0000000..029b4dc
--- /dev/null
+++ b/deltaspike/core/impl/src/main/java/org/apache/deltaspike/core/impl/message/TypedMessageBundleProducer.java
@@ -0,0 +1,44 @@
+/*
+ * 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 static org.apache.deltaspike.core.impl.message.MessageFactory.getBundle;
+import static org.apache.deltaspike.core.util.Reflections.getRawType;
+
+import java.io.Serializable;
+
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+/**
+ * The <code>TypedMessageBundleProducer</code> provides a producer method for
+ * injected typed message bundles.
+ */
+class TypedMessageBundleProducer implements Serializable
+{
+ private static final long serialVersionUID = -5077306523543940760L;
+
+ @Produces
+ @TypedMessageBundle
+ Object produceTypedMessageBundle(InjectionPoint injectionPoint)
+ {
+ return getBundle(getRawType(injectionPoint.getType()));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index 03621ae..21051db 100644
--- a/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/deltaspike/core/impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -18,4 +18,5 @@
#####################################################################################
org.apache.deltaspike.core.impl.exclude.ExcludeExtension
-org.apache.deltaspike.core.impl.config.injectable.ConfigPropertyExtension
\ No newline at end of file
+org.apache.deltaspike.core.impl.config.injectable.ConfigPropertyExtension
+org.apache.deltaspike.core.impl.message.MessageBundleExtension
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
new file mode 100644
index 0000000..8248933
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/BirdMessages.java
@@ -0,0 +1,28 @@
+/*
+ * 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.test.core.api.message;
+
+import org.apache.deltaspike.core.api.message.Message;
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+@MessageBundle
+public interface BirdMessages {
+ @Message("Spotted %s jays")
+ String numberOfJaysSpotted(int number);
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java
new file mode 100644
index 0000000..3dabbcb
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/Jay.java
@@ -0,0 +1,35 @@
+/*
+ * 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.test.core.api.message;
+
+import javax.inject.Inject;
+
+import org.apache.deltaspike.core.api.message.MessageBundle;
+
+public class Jay {
+
+ @Inject
+ @MessageBundle
+ BirdMessages messages;
+
+ String getMessage() {
+ return messages.numberOfJaysSpotted(8);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/11f95389/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
new file mode 100644
index 0000000..f196855
--- /dev/null
+++ b/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.test.core.api.message;
+
+import static org.junit.Assert.assertEquals;
+
+import javax.enterprise.inject.spi.Extension;
+
+import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
+import org.apache.deltaspike.core.impl.message.MessageBundleExtension;
+import org.apache.deltaspike.test.category.WebProfileCategory;
+import org.apache.deltaspike.test.util.ArchiveUtils;
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link org.apache.deltaspike.core.api.message.Message}
+ */
+@RunWith(Arquillian.class)
+@Category(WebProfileCategory.class)
+public class MessageTest
+{
+ /**
+ * X TODO creating a WebArchive is only a workaround because JavaArchive
+ * cannot contain other archives.
+ */
+ @Deployment
+ public static WebArchive deploy()
+ {
+ new BeanManagerProvider()
+ {
+ @Override
+ public void setTestMode()
+ {
+ super.setTestMode();
+ }
+ }.setTestMode();
+
+ JavaArchive testJar = ShrinkWrap
+ .create(JavaArchive.class, "messageTest.jar")
+ .addPackage("org.apache.deltaspike.test.core.api.message")
+ .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
+
+ return ShrinkWrap
+ .create(WebArchive.class, "messageTest.war")
+ .addAsLibraries(ArchiveUtils.getDeltaSpikeCoreArchive())
+ .addAsLibraries(testJar)
+ .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
+ .addAsServiceProvider(Extension.class,
+ MessageBundleExtension.class);
+ }
+
+ @Test
+ public void testMessageBundleInjection(Jay jay)
+ {
+ assertEquals("Spotted 8 jays", jay.getMessage());
+ }
+}