1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package javax.enterprise.inject; 20 21 import java.lang.annotation.Annotation; 22 import java.lang.reflect.Method; 23 import java.lang.reflect.ParameterizedType; 24 import java.lang.reflect.Type; 25 26 /** 27 * 28 * 29 * @param <T> wrapped annotation class 30 * @version $Rev$ $Date$ 31 */ 32 @SuppressWarnings("unchecked") 33 public abstract class AnnotationLiteral<T extends Annotation> implements Annotation 34 { 35 36 private Class<T> annotationType; 37 38 protected AnnotationLiteral() 39 { 40 this.annotationType = getAnnotationType(getClass()); 41 42 } 43 44 @Override 45 public Class<? extends Annotation> annotationType() 46 { 47 return annotationType; 48 } 49 50 protected Class<T> getAnnotationType(Class<?> definedClazz) 51 { 52 Type superClazz = definedClazz.getGenericSuperclass(); 53 Class<T> clazz = null; 54 55 if (superClazz instanceof ParameterizedType) 56 { 57 ParameterizedType paramType = (ParameterizedType) superClazz; 58 Type[] actualArgs = paramType.getActualTypeArguments(); 59 60 if (actualArgs.length == 1) 61 { 62 Type type = actualArgs[0]; 63 if (type instanceof Class) 64 { 65 clazz = (Class<T>) type; 66 return clazz; 67 } 68 else 69 { 70 throw new RuntimeException("Not class type"); 71 } 72 73 } 74 else 75 { 76 throw new RuntimeException("More than one parametric type"); 77 } 78 79 } 80 else 81 { 82 // Look for super, maybe inner 83 return getAnnotationType((Class<?>) superClazz); 84 } 85 86 } 87 88 @Override 89 public boolean equals(Object other) 90 { 91 Method[] methods = this.annotationType.getDeclaredMethods(); 92 93 if (other instanceof Annotation) 94 { 95 Annotation annotOther = (Annotation) other; 96 if (this.annotationType().equals(annotOther.annotationType())) 97 { 98 for (Method method : methods) 99 { 100 Object value = callMethod(this, method); 101 Object annotValue = callMethod(annotOther, method); 102 103 if (value != null && annotValue != null) 104 { 105 if (!value.equals(annotValue)) 106 { 107 return false; 108 } 109 } 110 else if ((value == null && annotValue != null) || (value != null && annotValue == null)) 111 { 112 return false; 113 } 114 115 } 116 return true; 117 } 118 } 119 120 return false; 121 } 122 123 protected Object callMethod(Object instance, Method method) 124 { 125 boolean access = method.isAccessible(); 126 127 try 128 { 129 130 if (!method.isAccessible()) 131 { 132 method.setAccessible(true); 133 } 134 135 return method.invoke(instance, new Object[] 136 { 137 }); 138 139 } 140 catch (Exception e) 141 { 142 throw new RuntimeException("Exception in method call : " + method.getName()); 143 } 144 finally 145 { 146 method.setAccessible(access); 147 } 148 149 150 } 151 152 @Override 153 public int hashCode() 154 { 155 Method[] methods = this.annotationType.getDeclaredMethods(); 156 157 int hashCode = 0; 158 for (Method method : methods) 159 { 160 // Member name 161 int name = 127 * method.getName().hashCode(); 162 163 // Member value 164 int value = callMethod(this, method).hashCode(); 165 hashCode += name ^ value; 166 } 167 return hashCode; 168 } 169 170 @Override 171 public String toString() 172 { 173 Method[] methods = this.annotationType.getDeclaredMethods(); 174 175 StringBuilder sb = new StringBuilder("@" + annotationType().getName() + "("); 176 int lenght = methods.length; 177 178 for (int i = 0; i < lenght; i++) 179 { 180 // Member name 181 sb.append(methods[i].getName()).append("="); 182 183 // Member value 184 sb.append(callMethod(this, methods[i])); 185 186 if (i < lenght - 1) 187 { 188 sb.append(","); 189 } 190 } 191 192 sb.append(")"); 193 194 return sb.toString(); 195 } 196 }