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 015package org.apache.tapestry.annotations; 016 017import java.lang.annotation.Annotation; 018import java.lang.reflect.Method; 019import java.util.Map; 020 021import org.apache.hivemind.ClassResolver; 022import org.apache.hivemind.ErrorLog; 023import org.apache.hivemind.Location; 024import org.apache.hivemind.Resource; 025import org.apache.hivemind.util.ClasspathResource; 026import org.apache.tapestry.enhance.EnhancementOperation; 027import org.apache.tapestry.enhance.EnhancementWorker; 028import org.apache.tapestry.spec.IComponentSpecification; 029import org.apache.tapestry.util.DescribedLocation; 030 031/** 032 * Implementation of {@link org.apache.tapestry.enhance.EnhancementWorker} that finds class and 033 * method annotations and delegates out to specific 034 * {@link org.apache.tapestry.annotations.ClassAnnotationEnhancementWorker} and 035 * {@link org.apache.tapestry.annotations.MethodAnnotationEnhancementWorker} instances. 036 * 037 * @author Howard M. Lewis Ship 038 * @since 4.0 039 */ 040public class AnnotationEnhancementWorker implements EnhancementWorker 041{ 042 private ClassResolver _classResolver; 043 044 private ErrorLog _errorLog; 045 046 private Map _methodWorkers; 047 048 private Map _classWorkers; 049 050 private SecondaryAnnotationWorker _secondaryAnnotationWorker; 051 052 public void setClassWorkers(Map classWorkers) 053 { 054 _classWorkers = classWorkers; 055 } 056 057 public void performEnhancement(EnhancementOperation op, IComponentSpecification spec) 058 { 059 Class clazz = op.getBaseClass(); 060 061 Resource classResource = newClassResource(clazz); 062 063 for (Annotation a : clazz.getAnnotations()) 064 { 065 performClassEnhancement(op, spec, clazz, a, classResource); 066 } 067 068 for (Method m : clazz.getMethods()) 069 { 070 performMethodEnhancement(op, spec, m, classResource); 071 } 072 } 073 074 private ClasspathResource newClassResource(Class clazz) 075 { 076 return new ClasspathResource(_classResolver, clazz.getName().replace('.', '/')); 077 } 078 079 void performClassEnhancement(EnhancementOperation op, IComponentSpecification spec, 080 Class clazz, Annotation annotation, Resource classResource) 081 { 082 ClassAnnotationEnhancementWorker worker = (ClassAnnotationEnhancementWorker) _classWorkers 083 .get(annotation.annotationType()); 084 085 if (worker == null) 086 return; 087 088 try 089 { 090 Location location = new DescribedLocation(classResource, AnnotationMessages 091 .classAnnotation(annotation, clazz)); 092 093 worker.performEnhancement(op, spec, clazz, location); 094 } 095 catch (Exception ex) 096 { 097 _errorLog.error(AnnotationMessages.failureProcessingClassAnnotation( 098 annotation, 099 clazz, 100 ex), null, ex); 101 } 102 103 } 104 105 void performMethodEnhancement(EnhancementOperation op, IComponentSpecification spec, 106 Method method, Resource classResource) 107 { 108 for (Annotation a : method.getAnnotations()) 109 { 110 performMethodEnhancement(op, spec, method, a, classResource); 111 } 112 113 try 114 { 115 // Remember; _secondaryWorker is a chain-of-command, so this returns true 116 // if any command in the chain returns true. 117 118 if (_secondaryAnnotationWorker.canEnhance(method)) 119 _secondaryAnnotationWorker.peformEnhancement(op, spec, method, classResource); 120 } 121 catch (Exception ex) 122 { 123 _errorLog.error(AnnotationMessages.failureEnhancingMethod(method, ex), null, ex); 124 } 125 } 126 127 void performMethodEnhancement(EnhancementOperation op, IComponentSpecification spec, 128 Method method, Annotation annotation, Resource classResource) 129 { 130 MethodAnnotationEnhancementWorker worker = (MethodAnnotationEnhancementWorker) _methodWorkers 131 .get(annotation.annotationType()); 132 133 if (worker == null) 134 return; 135 136 try 137 { 138 Location location = AnnotationUtils.buildLocationForAnnotation( 139 method, 140 annotation, 141 classResource); 142 worker.performEnhancement(op, spec, method, location); 143 } 144 catch (Exception ex) 145 { 146 _errorLog.error( 147 AnnotationMessages.failureProcessingAnnotation(annotation, method, ex), 148 null, 149 ex); 150 } 151 152 } 153 154 public void setMethodWorkers(Map methodWorkers) 155 { 156 _methodWorkers = methodWorkers; 157 } 158 159 public void setErrorLog(ErrorLog errorLog) 160 { 161 _errorLog = errorLog; 162 } 163 164 public void setClassResolver(ClassResolver classResolver) 165 { 166 _classResolver = classResolver; 167 } 168 169 public void setSecondaryAnnotationWorker(SecondaryAnnotationWorker secondaryWorker) 170 { 171 _secondaryAnnotationWorker = secondaryWorker; 172 } 173}