| /** |
| * Copyright (C) 2006 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.internal; |
| |
| import com.google.inject.BindingAnnotation; |
| import com.google.inject.Key; |
| import com.google.inject.ScopeAnnotation; |
| import com.google.inject.TypeLiteral; |
| import com.google.inject.internal.util.Classes; |
| import com.google.inject.name.Named; |
| import com.google.inject.name.Names; |
| import java.lang.annotation.Annotation; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.reflect.Member; |
| import javax.inject.Qualifier; |
| |
| /** |
| * Annotation utilities. |
| * |
| * @author crazybob@google.com (Bob Lee) |
| */ |
| public class Annotations { |
| |
| /** |
| * Returns {@code true} if the given annotation type has no attributes. |
| */ |
| public static boolean isMarker(Class<? extends Annotation> annotationType) { |
| return annotationType.getDeclaredMethods().length == 0; |
| } |
| |
| /** |
| * Returns true if the given annotation is retained at runtime. |
| */ |
| public static boolean isRetainedAtRuntime(Class<? extends Annotation> annotationType) { |
| Retention retention = annotationType.getAnnotation(Retention.class); |
| return retention != null && retention.value() == RetentionPolicy.RUNTIME; |
| } |
| |
| /** Returns the scope annotation on {@code type}, or null if none is specified. */ |
| public static Class<? extends Annotation> findScopeAnnotation( |
| Errors errors, Class<?> implementation) { |
| return findScopeAnnotation(errors, implementation.getAnnotations()); |
| } |
| |
| /** Returns the scoping annotation, or null if there isn't one. */ |
| public static Class<? extends Annotation> findScopeAnnotation(Errors errors, Annotation[] annotations) { |
| Class<? extends Annotation> found = null; |
| |
| for (Annotation annotation : annotations) { |
| Class<? extends Annotation> annotationType = annotation.annotationType(); |
| if (isScopeAnnotation(annotationType)) { |
| if (found != null) { |
| errors.duplicateScopeAnnotations(found, annotationType); |
| } else { |
| found = annotationType; |
| } |
| } |
| } |
| |
| return found; |
| } |
| |
| public static boolean isScopeAnnotation(Class<? extends Annotation> annotationType) { |
| return annotationType.isAnnotationPresent(ScopeAnnotation.class) |
| || annotationType.isAnnotationPresent(javax.inject.Scope.class); |
| } |
| |
| /** |
| * Adds an error if there is a misplaced annotations on {@code type}. Scoping |
| * annotations are not allowed on abstract classes or interfaces. |
| */ |
| public static void checkForMisplacedScopeAnnotations( |
| Class<?> type, Object source, Errors errors) { |
| if (Classes.isConcrete(type)) { |
| return; |
| } |
| |
| Class<? extends Annotation> scopeAnnotation = findScopeAnnotation(errors, type); |
| if (scopeAnnotation != null) { |
| errors.withSource(type).scopeAnnotationOnAbstractType(scopeAnnotation, type, source); |
| } |
| } |
| |
| /** Gets a key for the given type, member and annotations. */ |
| public static Key<?> getKey(TypeLiteral<?> type, Member member, Annotation[] annotations, |
| Errors errors) throws ErrorsException { |
| int numErrorsBefore = errors.size(); |
| Annotation found = findBindingAnnotation(errors, member, annotations); |
| errors.throwIfNewErrors(numErrorsBefore); |
| return found == null ? Key.get(type) : Key.get(type, found); |
| } |
| |
| /** |
| * Returns the binding annotation on {@code member}, or null if there isn't one. |
| */ |
| public static Annotation findBindingAnnotation( |
| Errors errors, Member member, Annotation[] annotations) { |
| Annotation found = null; |
| |
| for (Annotation annotation : annotations) { |
| Class<? extends Annotation> annotationType = annotation.annotationType(); |
| if (isBindingAnnotation(annotationType)) { |
| if (found != null) { |
| errors.duplicateBindingAnnotations(member, found.annotationType(), annotationType); |
| } else { |
| found = annotation; |
| } |
| } |
| } |
| |
| return found; |
| } |
| |
| /** |
| * Returns true if annotations of the specified type are binding annotations. |
| */ |
| public static boolean isBindingAnnotation(Class<? extends Annotation> annotationType) { |
| return annotationType.isAnnotationPresent(BindingAnnotation.class) |
| || annotationType.isAnnotationPresent(Qualifier.class); |
| } |
| |
| /** |
| * If the annotation is an instance of {@code javax.inject.Named}, canonicalizes to |
| * com.google.guice.name.Named. Returns the given annotation otherwise. |
| */ |
| public static Annotation canonicalizeIfNamed(Annotation annotation) { |
| if(annotation instanceof javax.inject.Named) { |
| return Names.named(((javax.inject.Named)annotation).value()); |
| } else { |
| return annotation; |
| } |
| } |
| |
| /** |
| * If the annotation is the class {@code javax.inject.Named}, canonicalizes to |
| * com.google.guice.name.Named. Returns the given annotation class otherwise. |
| */ |
| public static Class<? extends Annotation> canonicalizeIfNamed( |
| Class<? extends Annotation> annotationType) { |
| if (annotationType == javax.inject.Named.class) { |
| return Named.class; |
| } else { |
| return annotationType; |
| } |
| } |
| } |