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