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 18d736c6d053f63e4cd8dfb16c57093c67be3e18cdElliott Hughespackage libcore.reflect; 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 Project 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The annotation implementation based on dynamically generated proxy instances. 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It conforms to all requirements stated in public APIs, see in particular 36f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * {@link java.lang.reflect.AnnotatedElement java.lang.reflect.AnnotatedElement} 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and {@link java.lang.annotation.Annotation java.lang.annotation.Annotation}. 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Namely, annotation instances are immutable and serializable; they provide 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * conforming access to annotation member values and required implementations of 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * methods declared in Annotation interface. 41f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 421dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes * @see AnnotationMember 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.lang.annotation.Annotation 44f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @author Alexey V. Varlamov, Serguei S. Zapreyev 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @version $Revision$ 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project@SuppressWarnings({"serial"}) 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic final class AnnotationFactory implements InvocationHandler, Serializable { 50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 511dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes private static final transient Map<Class<? extends Annotation>, AnnotationMember[]> cache = 521dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>(); 53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 55f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Reflects specified annotation type and returns an array 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * of member element definitions with default values. 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 581dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType) { 591dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes synchronized (cache) { 601dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes AnnotationMember[] desc = cache.get(annotationType); 611dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes if (desc != null) { 621dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes return desc; 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 641dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes } 651dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes if (!annotationType.isAnnotation()) { 661dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes throw new IllegalArgumentException("Type is not annotation: " + annotationType.getName()); 671dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes } 681dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes Method[] declaredMethods = annotationType.getDeclaredMethods(); 691dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes AnnotationMember[] desc = new AnnotationMember[declaredMethods.length]; 701dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes for (int i = 0; i < declaredMethods.length; ++i) { 711dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes Method element = declaredMethods[i]; 721dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes String name = element.getName(); 731dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes Class<?> type = element.getReturnType(); 741dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes try { 751dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes desc[i] = new AnnotationMember(name, element.getDefaultValue(), type, element); 761dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes } catch (Throwable t) { 771dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes desc[i] = new AnnotationMember(name, t, type, element); 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 791dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes } 801dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes synchronized (cache) { 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cache.put(annotationType, desc); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return desc; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 85f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Provides a new annotation instance. 88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param annotationType the annotation type definition 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param elements name-value pairs representing elements of the annotation 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return a new annotation instance 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 9247f7d00f0edf404e1cac410334e1ea4d75a28b8dElliott Hughes public static <A extends Annotation> A createAnnotation(Class<? extends Annotation> annotationType, 9347f7d00f0edf404e1cac410334e1ea4d75a28b8dElliott Hughes AnnotationMember[] elements) { 941dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes AnnotationFactory factory = new AnnotationFactory(annotationType, elements); 9547f7d00f0edf404e1cac410334e1ea4d75a28b8dElliott Hughes return (A) Proxy.newProxyInstance(annotationType.getClassLoader(), 9647f7d00f0edf404e1cac410334e1ea4d75a28b8dElliott Hughes new Class[]{annotationType}, factory); 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Class<? extends Annotation> klazz; 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private AnnotationMember[] elements; 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * New instances should not be created directly, use factory method 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link #createAnnotation(Class, AnnotationMember[]) createAnnotation()} 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * instead. 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param klzz class defining the annotation type 108f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @param values actual element values 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private AnnotationFactory(Class<? extends Annotation> klzz, AnnotationMember[] values) { 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project klazz = klzz; 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] defs = getElementsDescription(klazz); 113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (values == null) { 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = defs; 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project //merge default and actual values 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = new AnnotationMember[defs.length]; 1181dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes next: for (int i = elements.length - 1; i >= 0; i--) { 1191dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes for (AnnotationMember val : values) { 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (val.name.equals(defs[i].name)) { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements[i] = val.setDefinition(defs[i]); 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue next; 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements[i] = defs[i]; 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 131f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Reads the object, obtains actual member definitions for the annotation type, 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * and merges deserialized values with the new definitions. 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1341dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes private void readObject(ObjectInputStream os) throws IOException, ClassNotFoundException { 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os.defaultReadObject(); 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Annotation type members can be changed arbitrarily 137f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // So there may be zombi elements from the previous life; 138f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // they hardly fit into this new annotation's incarnation, 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // as we have no defining methods for them. 140f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // Reasonably just drop such elements, 141f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // but seems better to keep them for compatibility 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] defs = getElementsDescription(klazz); 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember[] old = elements; 1441dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes List<AnnotationMember> merged = new ArrayList<AnnotationMember>(defs.length + old.length); 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project nextOld: for (AnnotationMember el1 : old) { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el2 : defs) { 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (el2.name.equals(el1.name)) { 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue nextOld; 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(el1); //phantom element 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1531dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes nextNew: for (AnnotationMember def : defs) { 1541dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes for (AnnotationMember val : old) { 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (val.name.equals(def.name)) { 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // nothing to do about cached errors (if any) 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // anyway they remain relevant to values 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(val.setDefinition(def)); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue nextNew; 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project merged.add(def); // brand new element 163f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project elements = merged.toArray(new AnnotationMember[merged.size()]); 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 166f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns true if the specified object represents the same annotation instance. 169f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * That is, if it implements the same annotation type and 170f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * returns the same element values. 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <br>Note, actual underlying implementation mechanism does not matter - it may 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * differ completely from this class. 173f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @return true if the passed object is equivalent annotation instance, 174f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * false otherwise. 1751dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes * @see AnnotationMember#equals(Object) 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean equals(Object obj) { 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (obj == this) { 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!klazz.isInstance(obj)) { 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object handler = null; 185f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes if (Proxy.isProxyClass(obj.getClass()) 1861dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory) { 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationFactory other = (AnnotationFactory) handler; 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (elements.length != other.elements.length) { 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1911dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes next: for (AnnotationMember el1 : elements) { 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el2 : other.elements) { 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (el1.equals(el2)) { 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project continue next; 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 2011dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes // encountered foreign annotation implementation 202f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // so have to obtain element values via invocation 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // of corresponding methods 204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (final AnnotationMember el : elements) { 2051dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes if (el.tag == AnnotationMember.ERROR) { 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // undefined value is incomparable (transcendent) 207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.definingMethod.isAccessible()) { 211ad41624e761bcf1af9c8008eb45187fc13983717Elliott Hughes el.definingMethod.setAccessible(true); 212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object otherValue = el.definingMethod.invoke(obj); 2141dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes if (otherValue != null) { 2151dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes if (el.tag == AnnotationMember.ARRAY) { 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.equalArrayValue(otherValue)) { 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!el.value.equals(otherValue)) { 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if (el.value != AnnotationMember.NO_VALUE) { 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (Throwable e) { 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 236f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Returns a hash code composed as a sum of hash codes of member elements, 237f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * including elements with default values. 2381dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes * @see AnnotationMember#hashCode() 239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int hashCode() { 241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int hash = 0; 242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember element : elements) { 243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project hash += element.hashCode(); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hash; 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Provides detailed description of this annotation instance, 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * including all member name-values pairs. 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return string representation of this annotation 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public String toString() { 2546aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes StringBuilder result = new StringBuilder(); 2556aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append('@'); 2566aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(klazz.getName()); 2576aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append('('); 2580d4daefcf389b6433a0af481ef44a84a2546541aElliott Hughes for (int i = 0; i < elements.length; ++i) { 2596aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes if (i != 0) { 2606aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(", "); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2626aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(elements[i]); 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2646aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes result.append(')'); 2656aa068b481cc4cca7765ce90fdf32f3eb2b5a77cElliott Hughes return result.toString(); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 267f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Processes a method invocation request to this annotation instance. 270f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * Recognizes the methods declared in the 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * {@link java.lang.annotation.Annotation java.lang.annotation.Annotation} 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * interface, and member-defining methods of the implemented annotation type. 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IllegalArgumentException If the specified method is none of the above 274f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * @return the invocation result 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2761dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project String name = method.getName(); 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Class[] params = method.getParameterTypes(); 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (params.length == 0) { 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ("annotationType".equals(name)) { 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return klazz; 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if ("toString".equals(name)) { 283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return toString(); 284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else if ("hashCode".equals(name)) { 285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return hashCode(); 286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 287f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // this must be element value request 289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project AnnotationMember element = null; 290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project for (AnnotationMember el : elements) { 291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (name.equals(el.name)) { 292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project element = el; 293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project break; 294f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes } 295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (element == null || !method.equals(element.definingMethod)) { 297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException(method.toString()); 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object value = element.validateValue(); 300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (value == null) { 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IncompleteAnnotationException(klazz, name); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return value; 304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3051dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)) { 306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return Boolean.valueOf(equals(args[0])); 307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 3081dc4d34e7de05c95b31a39e54d915f20240a4746Elliott Hughes throw new IllegalArgumentException("Invalid method for annotation type: " + method); 309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 311