001: /*******************************************************************************
002: * Portions created by Sebastian Thomschke are copyright (c) 2005-2007 Sebastian
003: * Thomschke.
004: *
005: * All Rights Reserved. This program and the accompanying materials
006: * are made available under the terms of the Eclipse Public License v1.0
007: * which accompanies this distribution, and is available at
008: * http://www.eclipse.org/legal/epl-v10.html
009: *
010: * Contributors:
011: * Sebastian Thomschke - initial implementation.
012: *******************************************************************************/package net.sf.oval.configuration.annotation;
013:
014: import java.lang.annotation.Annotation;
015: import java.lang.reflect.Constructor;
016: import java.lang.reflect.Field;
017: import java.lang.reflect.Method;
018: import java.util.List;
019:
020: import net.sf.oval.Check;
021: import net.sf.oval.configuration.Configurer;
022: import net.sf.oval.configuration.pojo.elements.ClassConfiguration;
023: import net.sf.oval.configuration.pojo.elements.ConstraintSetConfiguration;
024: import net.sf.oval.configuration.pojo.elements.ConstructorConfiguration;
025: import net.sf.oval.configuration.pojo.elements.FieldConfiguration;
026: import net.sf.oval.configuration.pojo.elements.MethodConfiguration;
027: import net.sf.oval.configuration.pojo.elements.MethodPostExecutionConfiguration;
028: import net.sf.oval.configuration.pojo.elements.MethodPreExecutionConfiguration;
029: import net.sf.oval.configuration.pojo.elements.MethodReturnValueConfiguration;
030: import net.sf.oval.configuration.pojo.elements.ObjectConfiguration;
031: import net.sf.oval.configuration.pojo.elements.ParameterConfiguration;
032: import net.sf.oval.exception.OValException;
033: import net.sf.oval.exception.ReflectionException;
034: import net.sf.oval.guard.Guarded;
035: import net.sf.oval.guard.Post;
036: import net.sf.oval.guard.PostCheck;
037: import net.sf.oval.guard.PostValidateThis;
038: import net.sf.oval.guard.Pre;
039: import net.sf.oval.guard.PreCheck;
040: import net.sf.oval.guard.PreValidateThis;
041: import net.sf.oval.internal.CollectionFactoryHolder;
042:
043: /**
044: * @author Sebastian Thomschke
045: */
046: public class AnnotationsConfigurer implements Configurer {
047: public ClassConfiguration getClassConfiguration(final Class<?> clazz)
048: throws OValException {
049: final ClassConfiguration config = new ClassConfiguration();
050: config.type = clazz;
051:
052: config.applyFieldConstraintsToConstructors = config.type
053: .isAnnotationPresent(Guarded.class) ? config.type
054: .getAnnotation(Guarded.class)
055: .applyFieldConstraintsToConstructors() : false;
056:
057: config.applyFieldConstraintsToSetters = config.type
058: .isAnnotationPresent(Guarded.class) ? config.type
059: .getAnnotation(Guarded.class)
060: .applyFieldConstraintsToSetters() : false;
061:
062: config.checkInvariants = config.type
063: .isAnnotationPresent(Guarded.class) ? config.type
064: .getAnnotation(Guarded.class).checkInvariants() : false;
065:
066: /*
067: * determine object-level checks
068: */
069: {
070: final List<Check> checks = CollectionFactoryHolder
071: .getFactory().createList(2);
072: for (final Annotation annotation : clazz.getAnnotations()) {
073: // check if the current annotation is a constraint annotation
074: if (annotation.annotationType().isAnnotationPresent(
075: Constraint.class)) {
076: checks.add(initializeCheck(annotation));
077: }
078: }
079: if (checks.size() > 0) {
080: config.objectConfiguration = new ObjectConfiguration();
081: config.objectConfiguration.checks = checks;
082: }
083: }
084:
085: /*
086: * determine field checks
087: */
088: for (final Field field : config.type.getDeclaredFields()) {
089: final List<Check> checks = CollectionFactoryHolder
090: .getFactory().createList(2);
091:
092: // loop over all annotations of the current field
093: for (final Annotation annotation : field.getAnnotations()) {
094: // check if the current annotation is a constraint annotation
095: if (annotation.annotationType().isAnnotationPresent(
096: Constraint.class)) {
097: checks.add(initializeCheck(annotation));
098: }
099: }
100: if (checks.size() > 0) {
101: if (config.fieldConfigurations == null)
102: config.fieldConfigurations = CollectionFactoryHolder
103: .getFactory().createSet(4);
104:
105: final FieldConfiguration fc = new FieldConfiguration();
106: fc.name = field.getName();
107: fc.checks = checks;
108: config.fieldConfigurations.add(fc);
109: }
110: }
111:
112: /*
113: * determine constructor parameter checks
114: */
115: for (final Constructor constructor : config.type
116: .getDeclaredConstructors()) {
117: final List<ParameterConfiguration> parametersConfig = CollectionFactoryHolder
118: .getFactory().createList(4);
119:
120: final Annotation[][] parameterAnnotations = constructor
121: .getParameterAnnotations();
122:
123: // loop over all parameters of the current constructor
124: for (int i = 0; i < parameterAnnotations.length; i++) {
125: final List<Check> parameterChecks = CollectionFactoryHolder
126: .getFactory().createList(4);
127:
128: // loop over all annotations of the current constructor parameter
129: for (final Annotation annotation : parameterAnnotations[i]) {
130: // check if the current annotation is a constraint annotation
131: if (annotation.annotationType()
132: .isAnnotationPresent(Constraint.class)) {
133: parameterChecks
134: .add(initializeCheck(annotation));
135: }
136: }
137:
138: final ParameterConfiguration pc = new ParameterConfiguration();
139: parametersConfig.add(pc);
140: pc.type = constructor.getParameterTypes()[i];
141: pc.checks = parameterChecks;
142: }
143: final boolean postValidateThis = constructor
144: .isAnnotationPresent(PostValidateThis.class);
145:
146: if (parametersConfig.size() > 0 | postValidateThis) {
147: if (config.constructorConfigurations == null)
148: config.constructorConfigurations = CollectionFactoryHolder
149: .getFactory().createSet(2);
150:
151: final ConstructorConfiguration cc = new ConstructorConfiguration();
152: cc.parameterConfigurations = parametersConfig;
153: cc.postCheckInvariants = postValidateThis;
154: config.constructorConfigurations.add(cc);
155: }
156: }
157:
158: /*
159: * determine method return value and parameter checks
160: */
161: for (final Method method : config.type.getDeclaredMethods()) {
162: /*
163: * determine method return value checks
164: */
165: final List<Check> returnValueChecks = CollectionFactoryHolder
166: .getFactory().createList(2);
167: final List<PreCheck> preChecks = CollectionFactoryHolder
168: .getFactory().createList(2);
169: final List<PostCheck> postChecks = CollectionFactoryHolder
170: .getFactory().createList(2);
171: boolean preValidateThis = false;
172: boolean postValidateThis = false;
173:
174: // loop over all annotations
175: for (final Annotation annotation : method.getAnnotations()) {
176: if (annotation instanceof Pre) {
177: final PreCheck pc = new PreCheck();
178: pc.configure((Pre) annotation);
179: preChecks.add(pc);
180: } else if (annotation instanceof PreValidateThis) {
181: preValidateThis = true;
182: } else if (annotation instanceof Post) {
183: final PostCheck pc = new PostCheck();
184: pc.configure((Post) annotation);
185: postChecks.add(pc);
186: } else if (annotation instanceof PostValidateThis) {
187: postValidateThis = true;
188: }
189:
190: // check if the current annotation is a constraint annotation
191: else if (annotation.annotationType()
192: .isAnnotationPresent(Constraint.class)) {
193: returnValueChecks.add(initializeCheck(annotation));
194: }
195: }
196:
197: /*
198: * determine parameter checks
199: */
200: final List<ParameterConfiguration> parametersConfig = CollectionFactoryHolder
201: .getFactory().createList(4);
202:
203: final Annotation[][] parameterAnnotations = method
204: .getParameterAnnotations();
205:
206: // loop over all parameters of the current method
207: for (int i = 0; i < parameterAnnotations.length; i++) {
208: final List<Check> parameterChecks = CollectionFactoryHolder
209: .getFactory().createList(4);
210:
211: // loop over all annotations of the current method parameter
212: for (final Annotation annotation : parameterAnnotations[i]) {
213: // check if the current annotation is a constraint annotation
214: if (annotation.annotationType()
215: .isAnnotationPresent(Constraint.class)) {
216: parameterChecks
217: .add(initializeCheck(annotation));
218: }
219: }
220:
221: final ParameterConfiguration pc = new ParameterConfiguration();
222: parametersConfig.add(pc);
223: pc.type = method.getParameterTypes()[i];
224: pc.checks = parameterChecks;
225: }
226:
227: if (parametersConfig.size() > 0
228: || returnValueChecks.size() > 0
229: || preChecks.size() > 0 || postChecks.size() > 0
230: || preValidateThis || postValidateThis) {
231: if (config.methodConfigurations == null)
232: config.methodConfigurations = CollectionFactoryHolder
233: .getFactory().createSet(4);
234:
235: final MethodConfiguration mc = new MethodConfiguration();
236: mc.name = method.getName();
237: mc.parameterConfigurations = parametersConfig;
238: mc.isInvariant = method
239: .isAnnotationPresent(IsInvariant.class);
240: mc.preCheckInvariants = preValidateThis;
241: mc.postCheckInvariants = postValidateThis;
242: if (returnValueChecks.size() > 0) {
243: mc.returnValueConfiguration = new MethodReturnValueConfiguration();
244: mc.returnValueConfiguration.checks = returnValueChecks;
245: }
246: if (preChecks.size() > 0) {
247: mc.preExecutionConfiguration = new MethodPreExecutionConfiguration();
248: mc.preExecutionConfiguration.checks = preChecks;
249: }
250: if (postChecks.size() > 0) {
251: mc.postExecutionConfiguration = new MethodPostExecutionConfiguration();
252: mc.postExecutionConfiguration.checks = postChecks;
253: }
254: config.methodConfigurations.add(mc);
255: }
256: }
257: return config;
258: }
259:
260: public ConstraintSetConfiguration getConstraintSetConfiguration(
261: final String constraintSetId) throws OValException {
262: return null;
263: }
264:
265: private <ConstraintAnnotation extends Annotation> AnnotationCheck<ConstraintAnnotation> initializeCheck(
266: final ConstraintAnnotation constraintAnnotation)
267: throws ReflectionException {
268: assert constraintAnnotation != null;
269:
270: final Constraint constraint = constraintAnnotation
271: .annotationType().getAnnotation(Constraint.class);
272: final Class checkClass = constraint.checkWith();
273:
274: try {
275: // instantiate the appropriate check for the found constraint
276: @SuppressWarnings("unchecked")
277: final AnnotationCheck<ConstraintAnnotation> check = (AnnotationCheck<ConstraintAnnotation>) checkClass
278: .newInstance();
279: check.configure(constraintAnnotation);
280: return check;
281: } catch (final Exception e) {
282: throw new ReflectionException(
283: "Cannot initialize constraint check "
284: + checkClass.getName(), e);
285: }
286: }
287: }
|