001 // Copyright 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry.annotations; 016 017 import java.lang.annotation.Annotation; 018 import java.lang.reflect.Method; 019 import java.util.ArrayList; 020 import java.util.Collections; 021 import java.util.List; 022 import java.util.Map; 023 024 import org.apache.hivemind.ClassResolver; 025 import org.apache.hivemind.ErrorLog; 026 import org.apache.hivemind.Location; 027 import org.apache.hivemind.Resource; 028 import org.apache.hivemind.impl.DefaultClassResolver; 029 import org.apache.tapestry.enhance.EnhancementOperation; 030 import org.apache.tapestry.spec.IComponentSpecification; 031 import org.apache.tapestry.util.DescribedLocation; 032 import static org.easymock.EasyMock.expect; 033 import static org.easymock.EasyMock.expectLastCall; 034 import org.testng.annotations.Test; 035 036 /** 037 * Tests for {@link org.apache.tapestry.annotations.AnnotationEnhancementWorker}. 038 * 039 * @author Howard M. Lewis Ship 040 * @since 4.0 041 */ 042 @Test 043 public class AnnotationEnhancementWorkerTest extends BaseAnnotationTestCase 044 { 045 protected EnhancementOperation newOp(Class baseClass) 046 { 047 EnhancementOperation op = newMock(EnhancementOperation.class); 048 049 expect(op.getBaseClass()).andReturn(baseClass); 050 051 return op; 052 } 053 054 protected Map newMap(Class annotationClass, Object worker) 055 { 056 return Collections.singletonMap(annotationClass, worker); 057 } 058 059 /** 060 * No method annotations registered. 061 */ 062 public void test_No_Annotations() 063 { 064 EnhancementOperation op = newOp(AnnotatedPage.class); 065 IComponentSpecification spec = newSpec(); 066 067 replay(); 068 069 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 070 worker.setMethodWorkers(Collections.EMPTY_MAP); 071 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 072 073 worker.performEnhancement(op, spec); 074 075 verify(); 076 } 077 078 public void test_Annotation_Match() 079 { 080 ClassResolver resolver = new DefaultClassResolver(); 081 082 EnhancementOperation op = newOp(AnnotatedPage.class); 083 IComponentSpecification spec = newSpec(); 084 085 MethodAnnotationEnhancementWorker methodWorker = newMethodAnnotationEnhancementWorker(); 086 087 Method m = findMethod(AnnotatedPage.class, "getInjectedObject"); 088 089 Location location = newMethodLocation(AnnotatedPage.class, m, InjectObject.class); 090 091 methodWorker.performEnhancement(op, spec, m, location); 092 093 replay(); 094 095 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 096 worker.setMethodWorkers(newMap(InjectObject.class, methodWorker)); 097 worker.setClassResolver(resolver); 098 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 099 100 worker.performEnhancement(op, spec); 101 102 verify(); 103 } 104 105 protected MethodAnnotationEnhancementWorker newMethodAnnotationEnhancementWorker() 106 { 107 return newMock(MethodAnnotationEnhancementWorker.class); 108 } 109 110 private DescribedLocation newClassLocation(Class baseClass, Class annotationClass) 111 { 112 Resource classResource = newResource(baseClass); 113 Annotation annotation = baseClass.getAnnotation(annotationClass); 114 115 return new DescribedLocation(classResource, AnnotationMessages.classAnnotation( 116 annotation, 117 baseClass)); 118 } 119 120 public void test_Annotation_With_Subclass() 121 { 122 ClassResolver resolver = new DefaultClassResolver(); 123 124 EnhancementOperation op = newOp(AnnotatedPageSubclass.class); 125 IComponentSpecification spec = newSpec(); 126 127 MethodAnnotationEnhancementWorker methodWorker = newMethodAnnotationEnhancementWorker(); 128 129 Method m = findMethod(AnnotatedPageSubclass.class, "getInjectedObject"); 130 131 Location location = newMethodLocation(AnnotatedPageSubclass.class, m, InjectObject.class); 132 133 methodWorker.performEnhancement(op, spec, m, location); 134 135 replay(); 136 137 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 138 worker.setMethodWorkers(newMap(InjectObject.class, methodWorker)); 139 worker.setClassResolver(resolver); 140 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 141 142 worker.performEnhancement(op, spec); 143 144 verify(); 145 } 146 147 public void test_Annotation_Failure() 148 { 149 ClassResolver resolver = new DefaultClassResolver(); 150 151 ErrorLog log = newErrorLog(); 152 Throwable t = new RuntimeException("Woops!"); 153 154 EnhancementOperation op = newOp(AnnotatedPage.class); 155 IComponentSpecification spec = newSpec(); 156 157 MethodAnnotationEnhancementWorker methodWorker = newMethodAnnotationEnhancementWorker(); 158 159 Method m = findMethod(AnnotatedPage.class, "getInjectedObject"); 160 161 Location location = newMethodLocation(AnnotatedPage.class, m, InjectObject.class); 162 163 methodWorker.performEnhancement(op, spec, m, location); 164 expectLastCall().andThrow(t); 165 166 log.error("An error occured processing annotation " 167 + "@org.apache.tapestry.annotations.InjectObject(value=barney) of " 168 + "public abstract java.lang.Object org.apache.tapestry.annotations.AnnotatedPage.getInjectedObject(): Woops!", 169 null, 170 t); 171 172 replay(); 173 174 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 175 worker.setMethodWorkers(newMap(InjectObject.class, methodWorker)); 176 worker.setErrorLog(log); 177 worker.setClassResolver(resolver); 178 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 179 180 worker.performEnhancement(op, spec); 181 182 verify(); 183 } 184 185 public void test_Class_Annotation() 186 { 187 ClassResolver resolver = new DefaultClassResolver(); 188 189 EnhancementOperation op = newOp(DeprecatedBean.class); 190 IComponentSpecification spec = newSpec(); 191 192 ClassAnnotationEnhancementWorker classWorker = newMock(ClassAnnotationEnhancementWorker.class); 193 194 DescribedLocation location = newClassLocation(DeprecatedBean.class, Deprecated.class); 195 196 classWorker.performEnhancement(op, spec, DeprecatedBean.class, location); 197 198 replay(); 199 200 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 201 worker.setClassWorkers(newMap(Deprecated.class, classWorker)); 202 worker.setClassResolver(resolver); 203 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 204 205 worker.performEnhancement(op, spec); 206 207 verify(); 208 } 209 210 public void test_Class_Annotation_Failure() 211 { 212 ClassResolver resolver = new DefaultClassResolver(); 213 214 ErrorLog log = newErrorLog(); 215 EnhancementOperation op = newOp(DeprecatedBean.class); 216 IComponentSpecification spec = newSpec(); 217 218 ClassAnnotationEnhancementWorker classWorker = newMock(ClassAnnotationEnhancementWorker.class); 219 220 Throwable t = new RuntimeException("Simulated failure."); 221 222 DescribedLocation location = newClassLocation(DeprecatedBean.class, Deprecated.class); 223 224 classWorker.performEnhancement(op, spec, DeprecatedBean.class, location); 225 expectLastCall().andThrow(t); 226 227 log.error("An error occured processing annotation @java.lang.Deprecated() of " 228 + "class org.apache.tapestry.annotations.DeprecatedBean: Simulated failure.", 229 null, 230 t); 231 232 replay(); 233 234 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 235 worker.setClassWorkers(newMap(Deprecated.class, classWorker)); 236 worker.setErrorLog(log); 237 worker.setClassResolver(resolver); 238 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 239 240 worker.performEnhancement(op, spec); 241 242 verify(); 243 } 244 245 public void test_Class_Annotation_No_Match() 246 { 247 EnhancementOperation op = newOp(DeprecatedBean.class); 248 IComponentSpecification spec = newSpec(); 249 250 replay(); 251 252 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 253 worker.setClassWorkers(Collections.EMPTY_MAP); 254 worker.setSecondaryAnnotationWorkers(Collections.EMPTY_LIST); 255 256 worker.performEnhancement(op, spec); 257 258 verify(); 259 } 260 261 public void test_Secondary_EnhancementWorker() 262 { 263 SecondaryAnnotationWorker secondary = newSecondaryAnnotationWorker(); 264 265 List<SecondaryAnnotationWorker> secWorkers = new ArrayList<SecondaryAnnotationWorker>(); 266 secWorkers.add(secondary); 267 268 EnhancementOperation op = newOp(); 269 IComponentSpecification spec = newSpec(); 270 Method method = findMethod(AnnotatedPage.class, "getPropertyWithInitialValue"); 271 272 Resource classResource = newResource(AnnotatedPage.class); 273 274 expect(secondary.canEnhance(method)).andReturn(true); 275 276 secondary.peformEnhancement(op, spec, method, classResource); 277 278 replay(); 279 280 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 281 worker.setSecondaryAnnotationWorkers(secWorkers); 282 worker.setMethodWorkers(Collections.EMPTY_MAP); 283 284 worker.performMethodEnhancement(op, spec, method, classResource); 285 286 verify(); 287 } 288 289 public void test_Secondary_EnhancementWorker_Failure() 290 { 291 SecondaryAnnotationWorker secondary = newSecondaryAnnotationWorker(); 292 293 List<SecondaryAnnotationWorker> secWorkers = new ArrayList<SecondaryAnnotationWorker>(); 294 secWorkers.add(secondary); 295 296 EnhancementOperation op = newOp(); 297 IComponentSpecification spec = newSpec(); 298 ErrorLog log = newErrorLog(); 299 300 Method method = findMethod(AnnotatedPage.class, "getPropertyWithInitialValue"); 301 302 Resource classResource = newResource(AnnotatedPage.class); 303 304 RuntimeException cause = new RuntimeException("Forced."); 305 306 expect(secondary.canEnhance(method)).andThrow(cause); 307 308 log.error(AnnotationMessages.failureEnhancingMethod(method, cause), null, cause); 309 310 replay(); 311 312 AnnotationEnhancementWorker worker = new AnnotationEnhancementWorker(); 313 worker.setSecondaryAnnotationWorkers(secWorkers); 314 worker.setMethodWorkers(Collections.EMPTY_MAP); 315 worker.setErrorLog(log); 316 317 worker.performMethodEnhancement(op, spec, method, classResource); 318 319 verify(); 320 } 321 322 protected SecondaryAnnotationWorker newSecondaryAnnotationWorker() 323 { 324 return newMock(SecondaryAnnotationWorker.class); 325 } 326 }