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 }