You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by sb...@apache.org on 2012/02/22 01:13:52 UTC
git commit: DELTASPIKE-69 Added utility classes required by security
module
Updated Branches:
refs/heads/master cf39ef9d5 -> 1177d4a7f
DELTASPIKE-69 Added utility classes required by security module
Project: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/commit/1177d4a7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/tree/1177d4a7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/diff/1177d4a7
Branch: refs/heads/master
Commit: 1177d4a7fd3e669eb84ce3987368d5ceaebfeb6a
Parents: cf39ef9
Author: Shane Bryzak <sb...@gmail.com>
Authored: Wed Feb 22 09:57:32 2012 +1000
Committer: Shane Bryzak <sb...@gmail.com>
Committed: Wed Feb 22 09:57:32 2012 +1000
----------------------------------------------------------------------
.../metadata/builder/ImmutableInjectionPoint.java | 151 +++++++++++++
.../api/metadata/builder/InjectableMethod.java | 167 +++++++++++++++
.../metadata/builder/ParameterValueRedefiner.java | 79 +++++++
.../org/apache/deltaspike/core/util/Beans.java | 138 ++++++++++++
4 files changed, 535 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1177d4a7/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ImmutableInjectionPoint.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ImmutableInjectionPoint.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ImmutableInjectionPoint.java
new file mode 100644
index 0000000..9d5180e
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ImmutableInjectionPoint.java
@@ -0,0 +1,151 @@
+package org.apache.deltaspike.core.api.metadata.builder;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.lang.reflect.Type;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.deltaspike.core.util.Beans;
+
+import static java.util.Collections.unmodifiableSet;
+
+/**
+ * <p>
+ * A base class for implementing {@link InjectionPoint}. The attributes are
+ * immutable, and collections are defensively copied on instantiation.
+ * </p>
+ *
+ * @author Stuart Douglas
+ * @author Pete Muir
+ */
+public class ImmutableInjectionPoint implements InjectionPoint {
+
+ private final Annotated annotated;
+ private final Member member;
+ private final Bean<?> declaringBean;
+ private final Set<Annotation> qualifiers;
+ private final Type type;
+ private final boolean _transient;
+ private final boolean delegate;
+
+ /**
+ * Instantiate a new {@link InjectionPoint} based upon an
+ * {@link AnnotatedField}.
+ *
+ * @param field the field for which to create the injection point
+ * @param qualifiers the qualifiers on the injection point
+ * @param declaringBean the declaringBean declaring the injection point
+ * @param _transient <code>true</code> if the injection point is transient
+ * @param delegate <code>true</code> if the injection point is a delegate
+ * injection point on a decorator
+ */
+ public ImmutableInjectionPoint(AnnotatedField<?> field, Set<Annotation> qualifiers, Bean<?> declaringBean, boolean _transient, boolean delegate) {
+ this.annotated = field;
+ this.member = field.getJavaMember();
+ this.qualifiers = new HashSet<Annotation>(qualifiers);
+ this.type = field.getJavaMember().getGenericType();
+ this._transient = _transient;
+ this.delegate = delegate;
+ this.declaringBean = declaringBean;
+ }
+
+ /**
+ * Instantiate a new {@link InjectionPoint} based upon an
+ * {@link AnnotatedField}, reading the qualifiers from the annotations
+ * declared on the field.
+ *
+ * @param field the field for which to create the injection point
+ * @param declaringBean the declaringBean declaring the injection point
+ * @param _transient <code>true</code> if the injection point is transient
+ * @param delegate <code>true</code> if the injection point is a delegate
+ * injection point on a decorator
+ */
+ public ImmutableInjectionPoint(AnnotatedField<?> field, BeanManager beanManager, Bean<?> declaringBean, boolean _transient, boolean delegate) {
+ this.annotated = field;
+ this.member = field.getJavaMember();
+ this.qualifiers = Beans.getQualifiers(beanManager, field.getAnnotations());
+ this.type = field.getJavaMember().getGenericType();
+ this._transient = _transient;
+ this.delegate = delegate;
+ this.declaringBean = declaringBean;
+ }
+
+ /**
+ * Instantiate a new {@link InjectionPoint} based upon an
+ * {@link AnnotatedParameter}.
+ *
+ * @param parameter the parameter for which to create the injection point
+ * @param qualifiers the qualifiers on the injection point
+ * @param declaringBean the declaringBean declaring the injection point
+ * @param _transient <code>true</code> if the injection point is transient
+ * @param delegate <code>true</code> if the injection point is a delegate
+ * injection point on a decorator
+ */
+ public ImmutableInjectionPoint(AnnotatedParameter<?> parameter, Set<Annotation> qualifiers, Bean<?> declaringBean, boolean _transient, boolean delegate) {
+ this.annotated = parameter;
+ this.member = parameter.getDeclaringCallable().getJavaMember();
+ this.qualifiers = new HashSet<Annotation>(qualifiers);
+ this._transient = _transient;
+ this.delegate = delegate;
+ this.declaringBean = declaringBean;
+ this.type = parameter.getBaseType();
+ }
+
+ /**
+ * Instantiate a new {@link InjectionPoint} based upon an
+ * {@link AnnotatedParameter}, reading the qualifiers from the annotations
+ * declared on the parameter.
+ *
+ * @param parameter the parameter for which to create the injection point
+ * @param declaringBean the declaringBean declaring the injection point
+ * @param _transient <code>true</code> if the injection point is transient
+ * @param delegate <code>true</code> if the injection point is a delegate
+ * injection point on a decorator
+ */
+ public ImmutableInjectionPoint(AnnotatedParameter<?> parameter, BeanManager beanManager, Bean<?> declaringBean, boolean _transient, boolean delegate) {
+ this.annotated = parameter;
+ this.member = parameter.getDeclaringCallable().getJavaMember();
+ this.qualifiers = Beans.getQualifiers(beanManager, parameter.getAnnotations());
+ this._transient = _transient;
+ this.delegate = delegate;
+ this.declaringBean = declaringBean;
+ this.type = parameter.getBaseType();
+ }
+
+ public Annotated getAnnotated() {
+ return annotated;
+ }
+
+ public Bean<?> getBean() {
+ return declaringBean;
+ }
+
+ public Member getMember() {
+ return member;
+ }
+
+ public Set<Annotation> getQualifiers() {
+ return unmodifiableSet(qualifiers);
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public boolean isDelegate() {
+ return delegate;
+ }
+
+ public boolean isTransient() {
+ return _transient;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1177d4a7/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/InjectableMethod.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/InjectableMethod.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/InjectableMethod.java
new file mode 100644
index 0000000..3ea3536
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/InjectableMethod.java
@@ -0,0 +1,167 @@
+package org.apache.deltaspike.core.api.metadata.builder;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.deltaspike.core.api.metadata.builder.ParameterValueRedefiner.ParameterValue;
+
+import static org.apache.deltaspike.core.util.Beans.createInjectionPoints;
+import static org.apache.deltaspike.core.util.Reflections.EMPTY_OBJECT_ARRAY;
+import static org.apache.deltaspike.core.util.Reflections.invokeMethod;
+
+/**
+ * <p>
+ * Allows an {@link AnnotatedMethod} to be injected using the CDI type safe
+ * resolution rules.
+ * </p>
+ * <p/>
+ * <p>
+ * {@link ParameterValueRedefiner} allows the default value to be overridden by
+ * the caller of
+ * {@link #invoke(Object, CreationalContext, ParameterValueRedefiner)}.
+ * </p>
+ *
+ * @param <X> the declaring type
+ * @author Pete Muir
+ */
+public class InjectableMethod<X> {
+
+ private final AnnotatedMethod<X> method;
+ private final List<InjectionPoint> parameters;
+ private final BeanManager beanManager;
+
+ /**
+ * Instantiate a new {@link InjectableMethod}.
+ *
+ * @param method the method which will be injected upon a call to
+ * {@link #invoke(Object, CreationalContext)}
+ * @param bean the bean which defines the injectable method
+ * @param beanManager the {@link BeanManager} to use to obtain the parameter
+ * values
+ */
+ public InjectableMethod(AnnotatedMethod<X> method, Bean<?> declaringBean, BeanManager beanManager) {
+ this(method, createInjectionPoints(method, declaringBean, beanManager), beanManager);
+ }
+
+ /**
+ * Instantiate a new {@link InjectableMethod}.
+ *
+ * @param method the method which will be injected upon a call to
+ * {@link #invoke(Object, CreationalContext)}
+ * @param parameters a collection of injection points representing the
+ * parameters of the method
+ * @param beanManager the {@link BeanManager} to use to obtain the parameter
+ * values
+ */
+ public InjectableMethod(AnnotatedMethod<X> method, Collection<InjectionPoint> parameters, BeanManager beanManager) {
+ this.method = method;
+ this.parameters = new ArrayList<InjectionPoint>(parameters);
+ this.beanManager = beanManager;
+ }
+
+ /**
+ * Get the bean manager used by this injectable method.
+ *
+ * @return the bean manager in use
+ */
+ protected BeanManager getBeanManager() {
+ return beanManager;
+ }
+
+ /**
+ * Get the injectable parameters of this method.
+ *
+ * @return a collection of injection points representing the parameters of
+ * this method
+ */
+ protected List<InjectionPoint> getParameters() {
+ return parameters;
+ }
+
+ /**
+ * Invoke the method, causing all parameters to be injected according to the
+ * CDI type safe resolution rules.public class ParameterValueRedefiner {
+
+}
+
+ *
+ * @param <T> the return type of the method
+ * @param receiver the instance upon which to call the method
+ * @param creationalContext the creational context to use to obtain
+ * injectable references for each parameter
+ * @return the result of invoking the method or null if the method's return
+ * type is void
+ * @throws RuntimeException if this <code>Method</code> object enforces Java
+ * language access control and the underlying method is
+ * inaccessible or if the underlying method throws an exception or
+ * if the initialization provoked by this method fails.
+ * @throws IllegalArgumentException if the method is an instance method and
+ * the specified <code>receiver</code> argument is not an instance
+ * of the class or interface declaring the underlying method (or
+ * of a subclass or implementor thereof); if an unwrapping
+ * conversion for primitive arguments fails; or if, after possible
+ * unwrapping, a parameter value cannot be converted to the
+ * corresponding formal parameter type by a method invocation
+ * conversion.
+ * @throws NullPointerException if the specified <code>receiver</code> is
+ * null and the method is an instance method.
+ * @throws ExceptionInInitializerError if the initialization provoked by this
+ * method fails.
+ */
+ public <T> T invoke(Object receiver, CreationalContext<T> creationalContext) {
+ return invoke(receiver, creationalContext, null);
+ }
+
+ /**
+ * Invoke the method, calling the parameter redefiner for each parameter,
+ * allowing the caller to override the default value obtained via the CDI
+ * type safe resolver.
+ *
+ * @param <T> the return type of the method
+ * @param receiver the instance upon which to call the method
+ * @param creationalContext the creational context to use to obtain
+ * injectable references for each parameter
+ * @return the result of invoking the method or null if the method's return
+ * type is void
+ * @throws RuntimeException if this <code>Method</code> object enforces Java
+ * language access control and the underlying method is
+ * inaccessible or if the underlying method throws an exception or
+ * if the initialization provoked by this method fails.
+ * @throws IllegalArgumentException if the method is an instance method and
+ * the specified <code>receiver</code> argument is not an instance
+ * of the class or interface declaring the underlying method (or
+ * of a subclass or implementor thereof); if an unwrapping
+ * conversion for primitive arguments fails; or if, after possible
+ * unwrapping, a parameter value cannot be converted to the
+ * corresponding formal parameter type by a method invocation
+ * conversion.
+ * @throws NullPointerException if the specified <code>receiver</code> is
+ * null and the method is an instance method.
+ * @throws ExceptionInInitializerError if the initialization provoked by this
+ * method fails.
+ */
+ public <T> T invoke(Object receiver, CreationalContext<T> creationalContext, ParameterValueRedefiner redefinition) {
+ List<Object> parameterValues = new ArrayList<Object>();
+ for (int i = 0; i < getParameters().size(); i++) {
+ if (redefinition != null) {
+ ParameterValue value = new ParameterValue(i, getParameters().get(i), getBeanManager());
+ parameterValues.add(redefinition.redefineParameterValue(value));
+ } else {
+ parameterValues.add(getBeanManager().getInjectableReference(getParameters().get(i), creationalContext));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ T result = (T) invokeMethod(true, method.getJavaMember(), receiver, parameterValues.toArray(EMPTY_OBJECT_ARRAY));
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1177d4a7/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ParameterValueRedefiner.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ParameterValueRedefiner.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ParameterValueRedefiner.java
new file mode 100644
index 0000000..be4b6d7
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/api/metadata/builder/ParameterValueRedefiner.java
@@ -0,0 +1,79 @@
+package org.apache.deltaspike.core.api.metadata.builder;
+
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+/**
+ * Provides the ability to redefine the value of a parameter on an
+ * {@link InjectableMethod} via the
+ * {@link #redefineParameterValue(ParameterValue)} callback.
+ *
+ * @author Pete Muir
+ * @see InjectableMethod
+ */
+public interface ParameterValueRedefiner {
+
+ /**
+ * Provides the default parameter's value, along with metadata about the
+ * parameter to a parameter redefinition.
+ *
+ * @author Pete Muir
+ * @see ParameterValueRedefiner
+ * @see InjectableMethod
+ */
+ public static class ParameterValue {
+
+ private final int position;
+ private final InjectionPoint injectionPoint;
+ private final BeanManager beanManager;
+
+ ParameterValue(int position, InjectionPoint injectionPoint, BeanManager beanManager) {
+ this.position = position;
+ this.injectionPoint = injectionPoint;
+ this.beanManager = beanManager;
+ }
+
+ /**
+ * Get the position of the parameter in the member's parameter list.
+ *
+ * @return the position of the parameter
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ /**
+ * Get the {@link InjectionPoint} for the parameter.
+ *
+ * @return the injection point
+ */
+ public InjectionPoint getInjectionPoint() {
+ return injectionPoint;
+ }
+
+ /**
+ * Get the default value of the parameter. The default value is that which
+ * would be injected according to the CDI type safe resolution rules.
+ *
+ * @param creationalContext the creationalContext to use to obtain the
+ * injectable reference.
+ * @return the default value
+ */
+ public Object getDefaultValue(CreationalContext<?> creationalContext) {
+ return beanManager.getInjectableReference(injectionPoint, creationalContext);
+ }
+
+ }
+
+ /**
+ * Callback allowing the default parameter value (that which would be
+ * injected according to the CDI type safe resolution rules) to be
+ * overridden.
+ *
+ * @param value the default value
+ * @return the overridden value
+ */
+ public Object redefineParameterValue(ParameterValue value);
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-deltaspike/blob/1177d4a7/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/Beans.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/Beans.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/Beans.java
new file mode 100644
index 0000000..f6c5a30
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/Beans.java
@@ -0,0 +1,138 @@
+package org.apache.deltaspike.core.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedParameter;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.inject.Inject;
+
+import org.apache.deltaspike.core.api.metadata.builder.ImmutableInjectionPoint;
+
+import static org.apache.deltaspike.core.util.Reflections.isSerializable;
+
+/**
+ * A set of utility methods for working with beans.
+ *
+ * @author Pete Muir
+ */
+public class Beans {
+
+ private Beans() {
+ }
+
+ /**
+ * Extract the qualifiers from a set of annotations.
+ *
+ * @param beanManager the beanManager to use to determine if an annotation is
+ * a qualifier
+ * @param annotations the annotations to check
+ * @return any qualifiers present in <code>annotations</code>
+ */
+ public static Set<Annotation> getQualifiers(BeanManager beanManager, Iterable<Annotation>... annotations) {
+ Set<Annotation> qualifiers = new HashSet<Annotation>();
+ for (Iterable<Annotation> annotationSet : annotations) {
+ for (Annotation annotation : annotationSet) {
+ if (beanManager.isQualifier(annotation.annotationType())) {
+ qualifiers.add(annotation);
+ }
+ }
+ }
+ return qualifiers;
+ }
+
+ /**
+ * Extract the qualifiers from a set of annotations.
+ *
+ * @param beanManager the beanManager to use to determine if an annotation is
+ * a qualifier
+ * @param annotations the annotations to check
+ * @return any qualifiers present in <code>annotations</code>
+ */
+ @SuppressWarnings("unchecked")
+ public static Set<Annotation> getQualifiers(BeanManager beanManager, Iterable<Annotation> annotations) {
+ return getQualifiers(beanManager, new Iterable[]{annotations});
+ }
+
+ /**
+ * Extract the qualifiers from a set of annotations.
+ *
+ * @param beanManager the beanManager to use to determine if an annotation is
+ * a qualifier
+ * @param annotations the annotations to check
+ * @return any qualifiers present in <code>annotations</code>
+ */
+ public static Set<Annotation> getQualifiers(BeanManager beanManager, Annotation[]... annotations) {
+ Set<Annotation> qualifiers = new HashSet<Annotation>();
+ for (Annotation[] annotationArray : annotations) {
+ for (Annotation annotation : annotationArray) {
+ if (beanManager.isQualifier(annotation.annotationType())) {
+ qualifiers.add(annotation);
+ }
+ }
+ }
+ return qualifiers;
+ }
+
+ public static void checkReturnValue(Object instance, Bean<?> bean, InjectionPoint injectionPoint, BeanManager beanManager) {
+ if (instance == null && !Dependent.class.equals(bean.getScope())) {
+ throw new IllegalStateException("Cannot return null from a non-dependent producer method: " + bean);
+ } else if (instance != null) {
+ boolean passivating = beanManager.isPassivatingScope(bean.getScope());
+ boolean instanceSerializable = isSerializable(instance.getClass());
+ if (passivating && !instanceSerializable) {
+ throw new IllegalStateException("Producers cannot declare passivating scope and return a non-serializable class: " + bean);
+ }
+ if (injectionPoint != null && injectionPoint.getBean() != null) {
+ if (!instanceSerializable && beanManager.isPassivatingScope(injectionPoint.getBean().getScope())) {
+ if (injectionPoint.getMember() instanceof Field) {
+ if (!injectionPoint.isTransient() && instance != null && !instanceSerializable) {
+ throw new IllegalStateException("Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans. Producer " + bean + "at injection point " + injectionPoint);
+ }
+ } else if (injectionPoint.getMember() instanceof Method) {
+ Method method = (Method) injectionPoint.getMember();
+ if (method.isAnnotationPresent(Inject.class)) {
+ throw new IllegalStateException("Producers cannot produce non-serializable instances for injection into parameters of initializers of beans declaring passivating scope. Producer " + bean + "at injection point " + injectionPoint);
+ }
+ if (method.isAnnotationPresent(Produces.class)) {
+ throw new IllegalStateException("Producers cannot produce non-serializable instances for injection into parameters of producer methods declaring passivating scope. Producer " + bean + "at injection point " + injectionPoint);
+ }
+ } else if (injectionPoint.getMember() instanceof Constructor<?>) {
+ throw new IllegalStateException("Producers cannot produce non-serializable instances for injection into parameters of constructors of beans declaring passivating scope. Producer " + bean + "at injection point " + injectionPoint);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Given a method, and the bean on which the method is declared, create a
+ * collection of injection points representing the parameters of the method.
+ *
+ * @param <X> the type declaring the method
+ * @param method the method
+ * @param declaringBean the bean on which the method is declared
+ * @param beanManager the bean manager to use to create the injection points
+ * @return the injection points
+ */
+ public static <X> List<InjectionPoint> createInjectionPoints(AnnotatedMethod<X> method, Bean<?> declaringBean, BeanManager beanManager) {
+ List<InjectionPoint> injectionPoints = new ArrayList<InjectionPoint>();
+ for (AnnotatedParameter<X> parameter : method.getParameters()) {
+ InjectionPoint injectionPoint = new ImmutableInjectionPoint(parameter, beanManager, declaringBean, false, false);
+ injectionPoints.add(injectionPoint);
+ }
+ return injectionPoints;
+ }
+
+}
\ No newline at end of file