AnnotationFactory.java revision 6aa068b481cc4cca7765ce90fdf32f3eb2b5a77c
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.lang.annotation; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.Serializable; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.annotation.Annotation; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.lang.annotation.IncompleteAnnotationException; 257365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.InvocationHandler; 267365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.Method; 277365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.lang.reflect.Proxy; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Map; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.WeakHashMap; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport static org.apache.harmony.lang.annotation.AnnotationMember.ARRAY; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport static org.apache.harmony.lang.annotation.AnnotationMember.ERROR; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The annotation implementation based on dynamically generated proxy instances. 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It conforms to all requirements stated in public APIs, see in particular 38f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * {@link java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedElement} 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and {@link java.lang.annotation.Annotation java.lang.annotation.Annotation}. 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Namely, annotation instances are immutable and serializable; they provide 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * conforming access to annotation member values and required implementations of 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * methods declared in Annotation interface. 43f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see android.lang.annotation.AnnotationMember 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.annotation.Annotation 46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Alexey V. Varlamov, Serguei S. Zapreyev 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @version $Revision$ 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project@SuppressWarnings({"serial"}) 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class AnnotationFactory implements InvocationHandler, Serializable { 52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private static final transient 54f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Map<Class<? extends Annotation>, AnnotationMember[]> 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cache = new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>(); 56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 58f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Reflects specified annotation type and returns an array 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of member element definitions with default values. 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType ) { 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] desc = cache.get(annotationType); 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (desc == null) { 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!annotationType.isAnnotation()) { 65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes throw new IllegalArgumentException("Type is not annotation: " 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project + annotationType.getName()); 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Method[] m = annotationType.getDeclaredMethods(); 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project desc = new AnnotationMember[m.length]; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int idx = 0; 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for(Method element : m) { 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = element.getName(); 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class<?> type = element.getReturnType(); 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes desc[idx] = new AnnotationMember(name, 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project element.getDefaultValue(), type, element); 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Throwable t) { 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project desc[idx] = new AnnotationMember(name, t, type, element); 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project idx++; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cache.put(annotationType, desc); 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return desc; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Provides a new annotation instance. 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param annotationType the annotation type definition 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param elements name-value pairs representing elements of the annotation 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new annotation instance 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static Annotation createAnnotation( 94f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes Class<? extends Annotation> annotationType, 95f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes AnnotationMember[] elements) 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { 97f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes AnnotationFactory antn = new AnnotationFactory(annotationType, elements); 98f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes return (Annotation)Proxy.newProxyInstance( annotationType.getClassLoader(), 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new Class[]{annotationType}, antn); 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Class<? extends Annotation> klazz; 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private AnnotationMember[] elements; 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * New instances should not be created directly, use factory method 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #createAnnotation(Class, AnnotationMember[]) createAnnotation()} 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * instead. 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param klzz class defining the annotation type 111f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @param values actual element values 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private AnnotationFactory(Class<? extends Annotation> klzz, AnnotationMember[] values) { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project klazz = klzz; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] defs = getElementsDescription(klazz); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (values == null) { 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = defs; 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //merge default and actual values 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = new AnnotationMember[defs.length]; 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next: for (int i = elements.length - 1; i >= 0; i-- ){ 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember val : values){ 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (val.name.equals(defs[i].name)) { 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements[i] = val.setDefinition(defs[i]); 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue next; 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements[i] = defs[i]; 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 134f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Reads the object, obtains actual member definitions for the annotation type, 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and merges deserialized values with the new definitions. 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 137f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private void readObject(ObjectInputStream os) throws IOException, 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ClassNotFoundException { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os.defaultReadObject(); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Annotation type members can be changed arbitrarily 141f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // So there may be zombi elements from the previous life; 142f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // they hardly fit into this new annotation's incarnation, 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // as we have no defining methods for them. 144f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // Reasonably just drop such elements, 145f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // but seems better to keep them for compatibility 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] defs = getElementsDescription(klazz); 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] old = elements; 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project List<AnnotationMember> merged = new ArrayList<AnnotationMember>( 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project defs.length + old.length); 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextOld: for (AnnotationMember el1 : old) { 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el2 : defs) { 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (el2.name.equals(el1.name)) { 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue nextOld; 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(el1); //phantom element 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextNew: for (AnnotationMember def : defs){ 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember val : old){ 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (val.name.equals(def.name)) { 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing to do about cached errors (if any) 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // anyway they remain relevant to values 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(val.setDefinition(def)); 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue nextNew; 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(def); // brand new element 168f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = merged.toArray(new AnnotationMember[merged.size()]); 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 171f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the specified object represents the same annotation instance. 174f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * That is, if it implements the same annotation type and 175f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * returns the same element values. 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <br>Note, actual underlying implementation mechanism does not matter - it may 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * differ completely from this class. 178f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @return true if the passed object is equivalent annotation instance, 179f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * false otherwise. 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see android.lang.annotation.AnnotationMember#equals(Object) 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object obj) { 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (obj == this) { 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!klazz.isInstance(obj)) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object handler = null; 190f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (Proxy.isProxyClass(obj.getClass()) 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationFactory other = (AnnotationFactory) handler; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (elements.length != other.elements.length) { 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project next: for (AnnotationMember el1 : elements){ 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el2 : other.elements) { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (el1.equals(el2)) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue next; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // encountered foreign annotation implementaton 207f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // so have to obtain element values via invocation 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // of corresponding methods 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (final AnnotationMember el : elements) { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (el.tag == ERROR) { 211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // undefined value is incomparable (transcendent) 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.definingMethod.isAccessible()) { 216ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes el.definingMethod.setAccessible(true); 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object otherValue = el.definingMethod.invoke(obj); 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (otherValue != null ) { 220f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (el.tag == ARRAY) { 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.equalArrayValue(otherValue)) { 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.value.equals(otherValue)) { 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (el.value != AnnotationMember.NO_VALUE) { 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Throwable e) { 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 241f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Returns a hash code composed as a sum of hash codes of member elements, 242f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * including elements with default values. 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see android.lang.annotation.AnnotationMember#hashCode() 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int hash = 0; 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember element : elements) { 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hash += element.hashCode(); 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash; 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Provides detailed description of this annotation instance, 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * including all member name-values pairs. 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return string representation of this annotation 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 2596aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes StringBuilder result = new StringBuilder(); 2606aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append('@'); 2616aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(klazz.getName()); 2626aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append('('); 2636aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes for(int i = 0; i < elements.length; ++i) { 2646aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes if (i != 0) { 2656aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(", "); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2676aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(elements[i]); 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2696aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(')'); 2706aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes return result.toString(); 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 272f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Processes a method invocation request to this annotation instance. 275f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Recognizes the methods declared in the 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link java.lang.annotation.Annotation java.lang.annotation.Annotation} 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * interface, and member-defining methods of the implemented annotation type. 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException If the specified method is none of the above 279f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @return the invocation result 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = method.getName(); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class[] params = method.getParameterTypes(); 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (params.length == 0) { 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ("annotationType".equals(name)) { 287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return klazz; 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if ("toString".equals(name)) { 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return toString(); 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if ("hashCode".equals(name)) { 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hashCode(); 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 293f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // this must be element value request 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember element = null; 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el : elements) { 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (name.equals(el.name)) { 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project element = el; 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 300f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (element == null || !method.equals(element.definingMethod)) { 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException(method.toString()); 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object value = element.validateValue(); 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value == null) { 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IncompleteAnnotationException(klazz, name); 308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return value; 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){ 312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Boolean.valueOf(equals(args[0])); 313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Invalid method for annotation type: " + method); 316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 318