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