Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Copyright (C) 2008 Google Inc.
*
* Licensed 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 com.google.inject.spi;
import com.google.inject.ConfigurationException;
import com.google.inject.Inject;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.Annotations;
import com.google.inject.internal.Errors;
import com.google.inject.internal.ErrorsException;
import com.google.inject.internal.ImmutableList;
import com.google.inject.internal.ImmutableSet;
import com.google.inject.internal.Lists;
import com.google.inject.internal.MoreTypes;
import static com.google.inject.internal.MoreTypes.getRawType;
import com.google.inject.internal.Nullability;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* A constructor, field or method that can receive injections. Typically this is a member with the
* {@literal @}{@link Inject} annotation. For non-private, no argument constructors, the member may
* omit the annotation.
*
* @author [email protected] (Bob Lee)
* @since 2.0
*/
public final class InjectionPoint {
private final boolean optional;
private final Member member;
private final ImmutableList> dependencies;
private InjectionPoint(Member member,
ImmutableList> dependencies, boolean optional) {
this.member = member;
this.dependencies = dependencies;
this.optional = optional;
}
InjectionPoint(TypeLiteral> type, Method method) {
this.member = method;
Inject inject = method.getAnnotation(Inject.class);
this.optional = inject.optional();
this.dependencies = forMember(method, type, method.getParameterAnnotations());
}
InjectionPoint(TypeLiteral> type, Constructor> constructor) {
this.member = constructor;
this.optional = false;
this.dependencies = forMember(constructor, type, constructor.getParameterAnnotations());
}
InjectionPoint(TypeLiteral> type, Field field) {
this.member = field;
Inject inject = field.getAnnotation(Inject.class);
this.optional = inject.optional();
Annotation[] annotations = field.getAnnotations();
Errors errors = new Errors(field);
Key> key = null;
try {
key = Annotations.getKey(type.getFieldType(field), field, annotations, errors);
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
errors.throwConfigurationExceptionIfErrorsExist();
this.dependencies = ImmutableList.>of(
newDependency(key, Nullability.allowsNull(annotations), -1));
}
private ImmutableList> forMember(Member member, TypeLiteral> type,
Annotation[][] paramterAnnotations) {
Errors errors = new Errors(member);
Iterator annotationsIterator = Arrays.asList(paramterAnnotations).iterator();
List> dependencies = Lists.newArrayList();
int index = 0;
for (TypeLiteral> parameterType : type.getParameterTypes(member)) {
try {
Annotation[] parameterAnnotations = annotationsIterator.next();
Key> key = Annotations.getKey(parameterType, member, parameterAnnotations, errors);
dependencies.add(newDependency(key, Nullability.allowsNull(parameterAnnotations), index));
index++;
} catch (ErrorsException e) {
errors.merge(e.getErrors());
}
}
errors.throwConfigurationExceptionIfErrorsExist();
return ImmutableList.copyOf(dependencies);
}
// This metohd is necessary to create a Dependency with proper generic type information
private Dependency newDependency(Key key, boolean allowsNull, int parameterIndex) {
return new Dependency(this, key, allowsNull, parameterIndex);
}
/**
* Returns the injected constructor, field, or method.
*/
public Member getMember() {
return member;
}
/**
* Returns the dependencies for this injection point. If the injection point is for a method or
* constructor, the dependencies will correspond to that member's parameters. Field injection
* points always have a single dependency for the field itself.
*
* @return a possibly-empty list
*/
public List> getDependencies() {
return dependencies;
}
/**
* Returns true if this injection point shall be skipped if the injector cannot resolve bindings
* for all required dependencies. Both explicit bindings (as specified in a module), and implicit
* bindings ({@literal @}{@link com.google.inject.ImplementedBy ImplementedBy}, default
* constructors etc.) may be used to satisfy optional injection points.
*/
public boolean isOptional() {
return optional;
}
@Override public boolean equals(Object o) {
return o instanceof InjectionPoint
&& member.equals(((InjectionPoint) o).member);
}
@Override public int hashCode() {
return member.hashCode();
}
@Override public String toString() {
return MoreTypes.toString(member);
}
/**
* Returns a new injection point for the injectable constructor of {@code type}.
*
* @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
* or a no-arguments constructor that is not private.
* @throws ConfigurationException if there is no injectable constructor, more than one injectable
* constructor, or if parameters of the injectable constructor are malformed, such as a
* parameter with multiple binding annotations.
*/
public static InjectionPoint forConstructorOf(TypeLiteral> type) {
Class> rawType = getRawType(type.getType());
Errors errors = new Errors(rawType);
Constructor> injectableConstructor = null;
for (Constructor> constructor : rawType.getDeclaredConstructors()) {
Inject inject = constructor.getAnnotation(Inject.class);
if (inject != null) {
if (inject.optional()) {
errors.optionalConstructor(constructor);
}
if (injectableConstructor != null) {
errors.tooManyConstructors(rawType);
}
injectableConstructor = constructor;
checkForMisplacedBindingAnnotations(injectableConstructor, errors);
}
}
errors.throwConfigurationExceptionIfErrorsExist();
if (injectableConstructor != null) {
return new InjectionPoint(type, injectableConstructor);
}
// If no annotated constructor is found, look for a no-arg constructor instead.
try {
Constructor> noArgConstructor = rawType.getDeclaredConstructor();
// Disallow private constructors on non-private classes (unless they have @Inject)
if (Modifier.isPrivate(noArgConstructor.getModifiers())
&& !Modifier.isPrivate(rawType.getModifiers())) {
errors.missingConstructor(rawType);
throw new ConfigurationException(errors.getMessages());
}
checkForMisplacedBindingAnnotations(noArgConstructor, errors);
return new InjectionPoint(type, noArgConstructor);
} catch (NoSuchMethodException e) {
errors.missingConstructor(rawType);
throw new ConfigurationException(errors.getMessages());
}
}
/**
* Returns a new injection point for the injectable constructor of {@code type}.
*
* @param type a concrete type with exactly one constructor annotated {@literal @}{@link Inject},
* or a no-arguments constructor that is not private.
* @throws ConfigurationException if there is no injectable constructor, more than one injectable
* constructor, or if parameters of the injectable constructor are malformed, such as a
* parameter with multiple binding annotations.
*/
public static InjectionPoint forConstructorOf(Class> type) {
return forConstructorOf(TypeLiteral.get(type));
}
/**
* Returns all static method and field injection points on {@code type}.
*
* @return a possibly empty set of injection points. The set has a specified iteration order. All
* fields are returned and then all methods. Within the fields, supertype fields are returned
* before subtype fields. Similarly, supertype methods are returned before subtype methods.
* @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
* a field with multiple binding annotations. The exception's {@link
* ConfigurationException#getPartialValue() partial value} is a {@code Set}
* of the valid injection points.
*/
public static Set forStaticMethodsAndFields(TypeLiteral type) {
List sink = Lists.newArrayList();
Errors errors = new Errors();
addInjectionPoints(type, Factory.FIELDS, true, sink, errors);
addInjectionPoints(type, Factory.METHODS, true, sink, errors);
ImmutableSet result = ImmutableSet.copyOf(sink);
if (errors.hasErrors()) {
throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
}
return result;
}
/**
* Returns all static method and field injection points on {@code type}.
*
* @return a possibly empty set of injection points. The set has a specified iteration order. All
* fields are returned and then all methods. Within the fields, supertype fields are returned
* before subtype fields. Similarly, supertype methods are returned before subtype methods.
* @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
* a field with multiple binding annotations. The exception's {@link
* ConfigurationException#getPartialValue() partial value} is a {@code Set}
* of the valid injection points.
*/
public static Set forStaticMethodsAndFields(Class> type) {
return forStaticMethodsAndFields(TypeLiteral.get(type));
}
/**
* Returns all instance method and field injection points on {@code type}.
*
* @return a possibly empty set of injection points. The set has a specified iteration order. All
* fields are returned and then all methods. Within the fields, supertype fields are returned
* before subtype fields. Similarly, supertype methods are returned before subtype methods.
* @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
* a field with multiple binding annotations. The exception's {@link
* ConfigurationException#getPartialValue() partial value} is a {@code Set}
* of the valid injection points.
*/
public static Set forInstanceMethodsAndFields(TypeLiteral> type) {
List sink = Lists.newArrayList();
Errors errors = new Errors();
// TODO (crazybob): Filter out overridden members.
addInjectionPoints(type, Factory.FIELDS, false, sink, errors);
addInjectionPoints(type, Factory.METHODS, false, sink, errors);
ImmutableSet result = ImmutableSet.copyOf(sink);
if (errors.hasErrors()) {
throw new ConfigurationException(errors.getMessages()).withPartialValue(result);
}
return result;
}
/**
* Returns all instance method and field injection points on {@code type}.
*
* @return a possibly empty set of injection points. The set has a specified iteration order. All
* fields are returned and then all methods. Within the fields, supertype fields are returned
* before subtype fields. Similarly, supertype methods are returned before subtype methods.
* @throws ConfigurationException if there is a malformed injection point on {@code type}, such as
* a field with multiple binding annotations. The exception's {@link
* ConfigurationException#getPartialValue() partial value} is a {@code Set}
* of the valid injection points.
*/
public static Set forInstanceMethodsAndFields(Class> type) {
return forInstanceMethodsAndFields(TypeLiteral.get(type));
}
private static void checkForMisplacedBindingAnnotations(Member member, Errors errors) {
Annotation misplacedBindingAnnotation = Annotations.findBindingAnnotation(
errors, member, ((AnnotatedElement) member).getAnnotations());
if (misplacedBindingAnnotation == null) {
return;
}
// don't warn about misplaced binding annotations on methods when there's a field with the same
// name. In Scala, fields always get accessor methods (that we need to ignore). See bug 242.
if (member instanceof Method) {
try {
if (member.getDeclaringClass().getDeclaredField(member.getName()) != null) {
return;
}
} catch (NoSuchFieldException ignore) {
}
}
errors.misplacedBindingAnnotation(member, misplacedBindingAnnotation);
}
private static void addInjectionPoints(TypeLiteral> type,
Factory factory, boolean statics, Collection injectionPoints,
Errors errors) {
if (type.getType() == Object.class) {
return;
}
// Add injectors for superclass first.
TypeLiteral> superType = type.getSupertype(type.getRawType().getSuperclass());
addInjectionPoints(superType, factory, statics, injectionPoints, errors);
// Add injectors for all members next
addInjectorsForMembers(type, factory, statics, injectionPoints, errors);
}
private static void addInjectorsForMembers(
TypeLiteral> typeLiteral, Factory factory, boolean statics,
Collection injectionPoints, Errors errors) {
for (M member : factory.getMembers(getRawType(typeLiteral.getType()))) {
if (isStatic(member) != statics) {
continue;
}
Inject inject = member.getAnnotation(Inject.class);
if (inject == null) {
continue;
}
try {
injectionPoints.add(factory.create(typeLiteral, member, errors));
} catch (ConfigurationException ignorable) {
if (!inject.optional()) {
errors.merge(ignorable.getErrorMessages());
}
}
}
}
private static boolean isStatic(Member member) {
return Modifier.isStatic(member.getModifiers());
}
private interface Factory {
Factory FIELDS = new Factory() {
public Field[] getMembers(Class> type) {
return type.getDeclaredFields();
}
public InjectionPoint create(TypeLiteral> typeLiteral, Field member, Errors errors) {
return new InjectionPoint(typeLiteral, member);
}
};
Factory METHODS = new Factory() {
public Method[] getMembers(Class> type) {
return type.getDeclaredMethods();
}
public InjectionPoint create(TypeLiteral> typeLiteral, Method member, Errors errors) {
checkForMisplacedBindingAnnotations(member, errors);
return new InjectionPoint(typeLiteral, member);
}
};
M[] getMembers(Class> type);
InjectionPoint create(TypeLiteral> typeLiteral, M member, Errors errors);
}
}