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.Map;
020    
021    import org.apache.hivemind.ClassResolver;
022    import org.apache.hivemind.ErrorLog;
023    import org.apache.hivemind.Location;
024    import org.apache.hivemind.Resource;
025    import org.apache.hivemind.util.ClasspathResource;
026    import org.apache.tapestry.enhance.EnhancementOperation;
027    import org.apache.tapestry.enhance.EnhancementWorker;
028    import org.apache.tapestry.spec.IComponentSpecification;
029    import 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     */
040    public 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    }