View Javadoc
1   /*******************************************************************************
2    * Portions created by Sebastian Thomschke are copyright (c) 2005-2013 Sebastian
3    * Thomschke.
4    *
5    * All Rights Reserved. This program and the accompanying materials
6    * are made available under the terms of the Eclipse Public License v1.0
7    * which accompanies this distribution, and is available at
8    * http://www.eclipse.org/legal/epl-v10.html
9    *
10   * Contributors:
11   *     Sebastian Thomschke - initial implementation.
12   *******************************************************************************/
13  package net.sf.oval.internal;
14  
15  import static net.sf.oval.Validator.*;
16  
17  import java.lang.reflect.AccessibleObject;
18  import java.lang.reflect.Constructor;
19  import java.lang.reflect.Field;
20  import java.lang.reflect.Method;
21  import java.util.Collection;
22  import java.util.LinkedHashSet;
23  import java.util.Map;
24  import java.util.Set;
25  
26  import net.sf.oval.Check;
27  import net.sf.oval.CheckExclusion;
28  import net.sf.oval.exception.InvalidConfigurationException;
29  import net.sf.oval.guard.IsGuarded;
30  import net.sf.oval.guard.ParameterNameResolver;
31  import net.sf.oval.guard.PostCheck;
32  import net.sf.oval.guard.PreCheck;
33  import net.sf.oval.internal.util.ArrayUtils;
34  import net.sf.oval.internal.util.ReflectionUtils;
35  
36  /**
37   * This class holds the instantiated checks for a single class.
38   *
39   * <b>Note:</b> For performance reasons the collections are made public (intended for read-access only).
40   * Modifications to the collections should be done through the appropriate methods addXXX, removeXXX, clearXXX methods.
41   *
42   * @author Sebastian Thomschke
43   */
44  public final class ClassChecks
45  {
46  	private static final String GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE = //
47  	" Class does not implement IsGuarded interface. This indicates, " + //
48  			"that constraints guarding may not activated for this class.";
49  
50  	private static final Log LOG = Log.getLog(ClassChecks.class);
51  
52  	/**
53  	 * checks on constructors' parameter values
54  	 */
55  	public final Map<Constructor< ? >, Map<Integer, ParameterChecks>> checksForConstructorParameters = getCollectionFactory().createMap(2);
56  
57  	/**
58  	 * checks on fields' value
59  	 */
60  	public final Map<Field, Set<Check>> checksForFields = getCollectionFactory().createMap();
61  
62  	/**
63  	 * checks on methods' parameter values
64  	 */
65  	public final Map<Method, Map<Integer, ParameterChecks>> checksForMethodParameters = getCollectionFactory().createMap();
66  
67  	/**
68  	 * checks on methods' return value
69  	 */
70  	public final Map<Method, Set<Check>> checksForMethodReturnValues = getCollectionFactory().createMap();
71  
72  	public final Map<Method, Set<PostCheck>> checksForMethodsPostExcecution = getCollectionFactory().createMap();
73  
74  	public final Map<Method, Set<PreCheck>> checksForMethodsPreExecution = getCollectionFactory().createMap();
75  
76  	/**
77  	 * compound constraints / object level invariants
78  	 */
79  	public final Set<Check> checksForObject = new LinkedHashSet<Check>(2);
80  
81  	public final Class< ? > clazz;
82  
83  	/**
84  	 * all non-static fields that have value constraints.
85  	 * Validator loops over this set during validation.
86  	 */
87  	public final Set<Field> constrainedFields = new LinkedHashSet<Field>();
88  
89  	/**
90  	 * all non-static non-void, non-parameterized methods marked as invariant that have return value constraints.
91  	 * Validator loops over this set during validation.
92  	 */
93  	public final Set<Method> constrainedMethods = new LinkedHashSet<Method>();
94  
95  	/**
96  	 * all non-static fields that have value constraints.
97  	 * Validator loops over this set during validation.
98  	 */
99  	public final Set<Field> constrainedStaticFields = new LinkedHashSet<Field>();
100 
101 	/**
102 	 * all static non-void, non-parameterized methods marked as invariant that have return value constraints.
103 	 * Validator loops over this set during validation.
104 	 */
105 	public final Set<Method> constrainedStaticMethods = new LinkedHashSet<Method>();
106 
107 	public boolean isCheckInvariants;
108 
109 	public final Set<AccessibleObject> methodsWithCheckInvariantsPost = getCollectionFactory().createSet();
110 
111 	public final Set<Method> methodsWithCheckInvariantsPre = getCollectionFactory().createSet();
112 
113 	private final ParameterNameResolver parameterNameResolver;
114 
115 	/**
116 	 * package constructor used by the Validator class
117 	 *
118 	 * @param clazz
119 	 */
120 	public ClassChecks(final Class< ? > clazz, final ParameterNameResolver parameterNameResolver)
121 	{
122 		LOG.debug("Initializing constraints configuration for class {1}", clazz);
123 
124 		this.clazz = clazz;
125 		this.parameterNameResolver = parameterNameResolver;
126 	}
127 
128 	private void _addConstructorParameterCheckExclusions(final Constructor< ? > constructor, final int parameterIndex,
129 			final Object exclusions) throws InvalidConfigurationException
130 	{
131 		final ParameterChecks checksOfConstructorParameter = _getChecksOfConstructorParameter(constructor, parameterIndex);
132 
133 		if (exclusions instanceof Collection< ? >)
134 		{
135 			@SuppressWarnings("unchecked")
136 			final Collection<CheckExclusion> exclusionsColl = (Collection<CheckExclusion>) exclusions;
137 			checksOfConstructorParameter.checkExclusions.addAll(exclusionsColl);
138 		}
139 		else
140 			ArrayUtils.addAll(checksOfConstructorParameter.checkExclusions, (CheckExclusion[]) exclusions);
141 	}
142 
143 	@SuppressWarnings("unchecked")
144 	private void _addConstructorParameterChecks(final Constructor< ? > constructor, final int parameterIndex, final Object checks)
145 			throws InvalidConfigurationException
146 	{
147 		if (LOG.isDebug() && !IsGuarded.class.isAssignableFrom(clazz))
148 			LOG.warn("Constructor parameter constraints may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
149 
150 		final ParameterChecks checksOfConstructorParameter = _getChecksOfConstructorParameter(constructor, parameterIndex);
151 
152 		if (checks instanceof Collection)
153 			for (final Check check : (Collection<Check>) checks)
154 			{
155 				checksOfConstructorParameter.checks.add(check);
156 				if (check.getContext() == null) check.setContext(checksOfConstructorParameter.context);
157 			}
158 		else
159 			for (final Check check : (Check[]) checks)
160 			{
161 				checksOfConstructorParameter.checks.add(check);
162 				if (check.getContext() == null) check.setContext(checksOfConstructorParameter.context);
163 			}
164 	}
165 
166 	@SuppressWarnings("unchecked")
167 	private void _addFieldChecks(final Field field, final Object checks)
168 	{
169 		synchronized (checksForFields)
170 		{
171 			Set<Check> checksOfField = checksForFields.get(field);
172 			if (checksOfField == null)
173 			{
174 				checksOfField = new LinkedHashSet<Check>(2);
175 				checksForFields.put(field, checksOfField);
176 				if (ReflectionUtils.isStatic(field))
177 					constrainedStaticFields.add(field);
178 				else
179 					constrainedFields.add(field);
180 			}
181 
182 			if (checks instanceof Collection)
183 				for (final Check check : (Collection<Check>) checks)
184 				{
185 					checksOfField.add(check);
186 					if (check.getContext() == null) check.setContext(ContextCache.getFieldContext(field));
187 				}
188 			else
189 				for (final Check check : (Check[]) checks)
190 				{
191 					checksOfField.add(check);
192 					if (check.getContext() == null) check.setContext(ContextCache.getFieldContext(field));
193 				}
194 		}
195 	}
196 
197 	private void _addMethodParameterCheckExclusions(final Method method, final int parameterIndex, final Object exclusions)
198 			throws InvalidConfigurationException
199 	{
200 		final ParameterChecks checksOfMethodParameter = _getChecksOfMethodParameter(method, parameterIndex);
201 
202 		if (exclusions instanceof Collection< ? >)
203 		{
204 			@SuppressWarnings("unchecked")
205 			final Collection<CheckExclusion> exclusionsColl = (Collection<CheckExclusion>) exclusions;
206 			checksOfMethodParameter.checkExclusions.addAll(exclusionsColl);
207 		}
208 		else
209 			ArrayUtils.addAll(checksOfMethodParameter.checkExclusions, (CheckExclusion[]) exclusions);
210 	}
211 
212 	@SuppressWarnings("unchecked")
213 	private void _addMethodParameterChecks(final Method method, final int parameterIndex, final Object checks)
214 			throws InvalidConfigurationException
215 	{
216 		if (LOG.isDebug() && !IsGuarded.class.isAssignableFrom(clazz))
217 			LOG.warn("Method parameter constraints may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
218 
219 		final ParameterChecks checksOfMethodParameter = _getChecksOfMethodParameter(method, parameterIndex);
220 
221 		if (checks instanceof Collection)
222 			for (final Check check : (Collection<Check>) checks)
223 			{
224 				if (check.getContext() == null) check.setContext(checksOfMethodParameter.context);
225 				checksOfMethodParameter.checks.add(check);
226 			}
227 		else
228 			for (final Check check : (Check[]) checks)
229 			{
230 				if (check.getContext() == null) check.setContext(checksOfMethodParameter.context);
231 				checksOfMethodParameter.checks.add(check);
232 			}
233 	}
234 
235 	@SuppressWarnings("unchecked")
236 	private void _addMethodPostChecks(final Method method, final Object checks) throws InvalidConfigurationException
237 	{
238 		if (LOG.isDebug() && !IsGuarded.class.isAssignableFrom(clazz))
239 			LOG.warn("Method post-conditions may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
240 
241 		synchronized (checksForMethodsPostExcecution)
242 		{
243 			Set<PostCheck> postChecks = checksForMethodsPostExcecution.get(method);
244 			if (postChecks == null)
245 			{
246 				postChecks = new LinkedHashSet<PostCheck>(2);
247 				checksForMethodsPostExcecution.put(method, postChecks);
248 			}
249 
250 			if (checks instanceof Collection)
251 				for (final PostCheck check : (Collection<PostCheck>) checks)
252 				{
253 					postChecks.add(check);
254 					if (check.getContext() == null) check.setContext(ContextCache.getMethodExitContext(method));
255 				}
256 			else
257 				for (final PostCheck check : (PostCheck[]) checks)
258 				{
259 					postChecks.add(check);
260 					if (check.getContext() == null) check.setContext(ContextCache.getMethodExitContext(method));
261 				}
262 		}
263 	}
264 
265 	@SuppressWarnings("unchecked")
266 	private void _addMethodPreChecks(final Method method, final Object checks) throws InvalidConfigurationException
267 	{
268 		if (LOG.isDebug() && !IsGuarded.class.isAssignableFrom(clazz))
269 			LOG.warn("Method pre-conditions may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
270 
271 		synchronized (checksForMethodsPreExecution)
272 		{
273 			Set<PreCheck> preChecks = checksForMethodsPreExecution.get(method);
274 			if (preChecks == null)
275 			{
276 				preChecks = new LinkedHashSet<PreCheck>(2);
277 				checksForMethodsPreExecution.put(method, preChecks);
278 			}
279 
280 			if (checks instanceof Collection)
281 				for (final PreCheck check : (Collection<PreCheck>) checks)
282 				{
283 					preChecks.add(check);
284 					if (check.getContext() == null) check.setContext(ContextCache.getMethodEntryContext(method));
285 				}
286 			else
287 				for (final PreCheck check : (PreCheck[]) checks)
288 				{
289 					preChecks.add(check);
290 					if (check.getContext() == null) check.setContext(ContextCache.getMethodEntryContext(method));
291 				}
292 		}
293 	}
294 
295 	@SuppressWarnings("unchecked")
296 	private void _addMethodReturnValueChecks(final Method method, final Boolean isInvariant, final Object checks)
297 			throws InvalidConfigurationException
298 	{
299 		// ensure the method has a return type
300 		if (method.getReturnType() == Void.TYPE)
301 			throw new InvalidConfigurationException("Adding return value constraints for method " + method
302 					+ " is not possible. The method is declared as void and does not return any values.");
303 
304 		if (ReflectionUtils.isVoidMethod(method))
305 			throw new InvalidConfigurationException("Cannot apply method return value constraints for void method " + method);
306 
307 		final boolean hasParameters = method.getParameterTypes().length > 0;
308 
309 		if (LOG.isDebug() && hasParameters && !IsGuarded.class.isAssignableFrom(clazz))
310 			LOG.warn("Method return value constraints may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
311 
312 		final boolean isInvariant2 = isInvariant == null ? constrainedMethods.contains(method) : isInvariant;
313 
314 		if (LOG.isDebug() && !isInvariant2 && !IsGuarded.class.isAssignableFrom(clazz))
315 			LOG.warn("Method return value constraints may not be validated." + GUARDING_MAY_NOT_BE_ACTIVATED_MESSAGE);
316 
317 		synchronized (checksForMethodReturnValues)
318 		{
319 			if (!hasParameters && isInvariant2)
320 			{
321 				if (ReflectionUtils.isStatic(method))
322 					constrainedStaticMethods.add(method);
323 				else
324 					constrainedMethods.add(method);
325 			}
326 			else if (ReflectionUtils.isStatic(method))
327 				constrainedStaticMethods.remove(method);
328 			else
329 				constrainedMethods.remove(method);
330 
331 			Set<Check> methodChecks = checksForMethodReturnValues.get(method);
332 			if (methodChecks == null)
333 			{
334 				methodChecks = new LinkedHashSet<Check>(2);
335 				checksForMethodReturnValues.put(method, methodChecks);
336 			}
337 
338 			if (checks instanceof Collection)
339 				for (final Check check : (Collection<Check>) checks)
340 				{
341 					methodChecks.add(check);
342 					if (check.getContext() == null) check.setContext(ContextCache.getMethodReturnValueContext(method));
343 				}
344 			else
345 				for (final Check check : (Check[]) checks)
346 				{
347 					methodChecks.add(check);
348 					if (check.getContext() == null) check.setContext(ContextCache.getMethodReturnValueContext(method));
349 				}
350 		}
351 	}
352 
353 	private ParameterChecks _getChecksOfConstructorParameter(final Constructor< ? > ctor, final int paramIndex)
354 	{
355 		final int paramCount = ctor.getParameterTypes().length;
356 
357 		if (paramIndex < 0 || paramIndex >= paramCount)
358 			throw new InvalidConfigurationException("Parameter Index " + paramIndex + " is out of range (0-" + (paramCount - 1) + ")");
359 
360 		synchronized (checksForConstructorParameters)
361 		{
362 			// retrieve the currently registered checks for all parameters of the specified constructor
363 			Map<Integer, ParameterChecks> checksOfConstructorByParameter = checksForConstructorParameters.get(ctor);
364 			if (checksOfConstructorByParameter == null)
365 			{
366 				checksOfConstructorByParameter = getCollectionFactory().createMap(paramCount);
367 				checksForConstructorParameters.put(ctor, checksOfConstructorByParameter);
368 			}
369 
370 			// retrieve the checks for the specified parameter
371 			ParameterChecks checksOfConstructorParameter = checksOfConstructorByParameter.get(paramIndex);
372 			if (checksOfConstructorParameter == null)
373 			{
374 				checksOfConstructorParameter = new ParameterChecks(ctor, paramIndex,
375 						parameterNameResolver.getParameterNames(ctor)[paramIndex]);
376 				checksOfConstructorByParameter.put(paramIndex, checksOfConstructorParameter);
377 			}
378 
379 			return checksOfConstructorParameter;
380 		}
381 	}
382 
383 	private ParameterChecks _getChecksOfMethodParameter(final Method method, final int paramIndex)
384 	{
385 		final int paramCount = method.getParameterTypes().length;
386 
387 		if (paramIndex < 0 || paramIndex >= paramCount)
388 			throw new InvalidConfigurationException("Parameter index " + paramIndex + " is out of range (0-" + (paramCount - 1) + ")");
389 
390 		synchronized (checksForMethodParameters)
391 		{
392 			// retrieve the currently registered checks for all parameters of the specified method
393 			Map<Integer, ParameterChecks> checksOfMethodByParameter = checksForMethodParameters.get(method);
394 			if (checksOfMethodByParameter == null)
395 			{
396 				checksOfMethodByParameter = getCollectionFactory().createMap(paramCount);
397 				checksForMethodParameters.put(method, checksOfMethodByParameter);
398 			}
399 
400 			// retrieve the checks for the specified parameter
401 			ParameterChecks checksOfMethodParameter = checksOfMethodByParameter.get(paramIndex);
402 			if (checksOfMethodParameter == null)
403 			{
404 				checksOfMethodParameter = new ParameterChecks(method, paramIndex,
405 						parameterNameResolver.getParameterNames(method)[paramIndex]);
406 				checksOfMethodByParameter.put(paramIndex, checksOfMethodParameter);
407 			}
408 
409 			return checksOfMethodParameter;
410 		}
411 	}
412 
413 	/**
414 	 * adds constraint check exclusions to a constructor parameter
415 	 *
416 	 * @param constructor
417 	 * @param parameterIndex
418 	 * @param exclusions
419 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
420 	 */
421 	public void addConstructorParameterCheckExclusions(final Constructor< ? > constructor, final int parameterIndex,
422 			final CheckExclusion... exclusions) throws InvalidConfigurationException
423 	{
424 		_addConstructorParameterCheckExclusions(constructor, parameterIndex, exclusions);
425 	}
426 
427 	/**
428 	 * adds constraint check exclusions to a constructor parameter
429 	 *
430 	 * @param constructor
431 	 * @param parameterIndex
432 	 * @param exclusions
433 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
434 	 */
435 	public void addConstructorParameterCheckExclusions(final Constructor< ? > constructor, final int parameterIndex,
436 			final Collection<CheckExclusion> exclusions) throws InvalidConfigurationException
437 	{
438 		_addConstructorParameterCheckExclusions(constructor, parameterIndex, exclusions);
439 	}
440 
441 	/**
442 	 * adds constraint checks to a constructor parameter
443 	 *
444 	 * @param constructor
445 	 * @param parameterIndex
446 	 * @param checks
447 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
448 	 */
449 	public void addConstructorParameterChecks(final Constructor< ? > constructor, final int parameterIndex, final Check... checks)
450 			throws InvalidConfigurationException
451 	{
452 		_addConstructorParameterChecks(constructor, parameterIndex, checks);
453 	}
454 
455 	/**
456 	 * adds constraint checks to a constructor parameter
457 	 *
458 	 * @param constructor
459 	 * @param parameterIndex
460 	 * @param checks
461 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
462 	 */
463 	public void addConstructorParameterChecks(final Constructor< ? > constructor, final int parameterIndex, final Collection<Check> checks)
464 			throws InvalidConfigurationException
465 	{
466 		_addConstructorParameterChecks(constructor, parameterIndex, checks);
467 	}
468 
469 	/**
470 	 * adds check constraints to a field
471 	 *
472 	 * @param field
473 	 * @param checks
474 	 */
475 	public void addFieldChecks(final Field field, final Check... checks) throws InvalidConfigurationException
476 	{
477 		_addFieldChecks(field, checks);
478 	}
479 
480 	/**
481 	 * adds check constraints to a field
482 	 *
483 	 * @param field
484 	 * @param checks
485 	 */
486 	public void addFieldChecks(final Field field, final Collection<Check> checks) throws InvalidConfigurationException
487 	{
488 		_addFieldChecks(field, checks);
489 	}
490 
491 	/**
492 	 * adds constraint check exclusions to a method parameter
493 	 *
494 	 * @param method
495 	 * @param parameterIndex
496 	 * @param exclusions
497 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
498 	 */
499 	public void addMethodParameterCheckExclusions(final Method method, final int parameterIndex, final CheckExclusion... exclusions)
500 			throws InvalidConfigurationException
501 	{
502 		_addMethodParameterCheckExclusions(method, parameterIndex, exclusions);
503 	}
504 
505 	/**
506 	 * adds constraint check exclusions to a method parameter
507 	 *
508 	 * @param method
509 	 * @param parameterIndex
510 	 * @param exclusions
511 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
512 	 */
513 	public void addMethodParameterCheckExclusions(final Method method, final int parameterIndex, final Collection<CheckExclusion> exclusions)
514 			throws InvalidConfigurationException
515 	{
516 		_addMethodParameterCheckExclusions(method, parameterIndex, exclusions);
517 	}
518 
519 	/**
520 	 * adds constraint checks to a method parameter
521 	 *
522 	 * @param method
523 	 * @param parameterIndex
524 	 * @param checks
525 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
526 	 */
527 	public void addMethodParameterChecks(final Method method, final int parameterIndex, final Check... checks)
528 			throws InvalidConfigurationException
529 	{
530 		_addMethodParameterChecks(method, parameterIndex, checks);
531 	}
532 
533 	/**
534 	 * adds constraint checks to a method parameter
535 	 *
536 	 * @param method
537 	 * @param parameterIndex
538 	 * @param checks
539 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
540 	 */
541 	public void addMethodParameterChecks(final Method method, final int parameterIndex, final Collection<Check> checks)
542 			throws InvalidConfigurationException
543 	{
544 		_addMethodParameterChecks(method, parameterIndex, checks);
545 	}
546 
547 	/**
548 	 * adds constraint checks to a method's return value
549 	 * @param method
550 	 * @param checks
551 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
552 	 */
553 	public void addMethodPostChecks(final Method method, final Collection<PostCheck> checks) throws InvalidConfigurationException
554 	{
555 		_addMethodPostChecks(method, checks);
556 	}
557 
558 	/**
559 	 * adds constraint checks to a method's return value
560 	 * @param method
561 	 * @param checks
562 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
563 	 */
564 	public void addMethodPostChecks(final Method method, final PostCheck... checks) throws InvalidConfigurationException
565 	{
566 		_addMethodPostChecks(method, checks);
567 	}
568 
569 	/**
570 	 * @param method
571 	 * @param checks
572 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
573 	 */
574 	public void addMethodPreChecks(final Method method, final Collection<PreCheck> checks) throws InvalidConfigurationException
575 	{
576 		_addMethodPreChecks(method, checks);
577 	}
578 
579 	/**
580 	 * @param method
581 	 * @param checks
582 	 * @throws InvalidConfigurationException if the declaring class is not guarded by GuardAspect
583 	 */
584 	public void addMethodPreChecks(final Method method, final PreCheck... checks) throws InvalidConfigurationException
585 	{
586 		_addMethodPreChecks(method, checks);
587 	}
588 
589 	/**
590 	 * adds constraint checks to a method's return value
591 	 * @param method
592 	 * @param isInvariant determines if the return value should be checked when the object is validated, can be null
593 	 * @param checks
594 	 */
595 	public void addMethodReturnValueChecks(final Method method, final Boolean isInvariant, final Check... checks)
596 			throws InvalidConfigurationException
597 	{
598 		_addMethodReturnValueChecks(method, isInvariant, checks);
599 	}
600 
601 	/**
602 	 * adds constraint checks to a method's return value
603 	 * @param method
604 	 * @param isInvariant determines if the return value should be checked when the object is validated, can be null
605 	 * @param checks
606 	 */
607 	public void addMethodReturnValueChecks(final Method method, final Boolean isInvariant, final Collection<Check> checks)
608 			throws InvalidConfigurationException
609 	{
610 		_addMethodReturnValueChecks(method, isInvariant, checks);
611 	}
612 
613 	/**
614 	 * adds check constraints on object level (invariants)
615 	 *
616 	 * @param checks
617 	 */
618 	public void addObjectChecks(final Check... checks)
619 	{
620 		synchronized (checksForObject)
621 		{
622 			for (final Check check : checks)
623 			{
624 				if (check.getContext() == null) check.setContext(ContextCache.getClassContext(clazz));
625 				checksForObject.add(check);
626 			}
627 		}
628 	}
629 
630 	/**
631 	 * adds check constraints on object level (invariants)
632 	 *
633 	 * @param checks
634 	 */
635 	public void addObjectChecks(final Collection<Check> checks)
636 	{
637 		synchronized (checksForObject)
638 		{
639 			for (final Check check : checks)
640 			{
641 				if (check.getContext() == null) check.setContext(ContextCache.getClassContext(clazz));
642 				checksForObject.add(check);
643 			}
644 		}
645 	}
646 
647 	public synchronized void clear()
648 	{
649 		LOG.debug("Clearing all checks for class {1}", clazz);
650 
651 		checksForObject.clear();
652 		checksForMethodsPostExcecution.clear();
653 		checksForMethodsPreExecution.clear();
654 		checksForConstructorParameters.clear();
655 		checksForFields.clear();
656 		checksForMethodReturnValues.clear();
657 		checksForMethodParameters.clear();
658 		constrainedFields.clear();
659 		constrainedStaticFields.clear();
660 		constrainedMethods.clear();
661 		constrainedStaticMethods.clear();
662 	}
663 
664 	public void clearConstructorChecks(final Constructor< ? > constructor)
665 	{
666 		clearConstructorParameterChecks(constructor);
667 	}
668 
669 	public void clearConstructorParameterChecks(final Constructor< ? > constructor)
670 	{
671 		synchronized (checksForConstructorParameters)
672 		{
673 			checksForConstructorParameters.remove(constructor);
674 		}
675 	}
676 
677 	public void clearConstructorParameterChecks(final Constructor< ? > constructor, final int parameterIndex)
678 	{
679 		synchronized (checksForConstructorParameters)
680 		{
681 			// retrieve the currently registered checks for all parameters of the specified method
682 			final Map<Integer, ParameterChecks> checksOfConstructorByParameter = checksForConstructorParameters.get(constructor);
683 			if (checksOfConstructorByParameter == null) return;
684 
685 			// retrieve the checks for the specified parameter
686 			final ParameterChecks checksOfMethodParameter = checksOfConstructorByParameter.get(parameterIndex);
687 			if (checksOfMethodParameter == null) return;
688 
689 			checksOfConstructorByParameter.remove(parameterIndex);
690 		}
691 	}
692 
693 	public void clearFieldChecks(final Field field)
694 	{
695 		synchronized (checksForFields)
696 		{
697 			checksForFields.remove(field);
698 			constrainedFields.remove(field);
699 			constrainedStaticFields.remove(field);
700 		}
701 	}
702 
703 	public synchronized void clearMethodChecks(final Method method)
704 	{
705 		clearMethodParameterChecks(method);
706 		clearMethodReturnValueChecks(method);
707 		clearMethodPreChecks(method);
708 		clearMethodPostChecks(method);
709 	}
710 
711 	public void clearMethodParameterChecks(final Method method)
712 	{
713 		synchronized (checksForMethodParameters)
714 		{
715 			checksForMethodParameters.remove(method);
716 		}
717 	}
718 
719 	public void clearMethodParameterChecks(final Method method, final int parameterIndex)
720 	{
721 		synchronized (checksForMethodParameters)
722 		{
723 			// retrieve the currently registered checks for all parameters of the specified method
724 			final Map<Integer, ParameterChecks> checksOfMethodByParameter = checksForMethodParameters.get(method);
725 			if (checksOfMethodByParameter == null) return;
726 
727 			// retrieve the checks for the specified parameter
728 			final ParameterChecks checksOfMethodParameter = checksOfMethodByParameter.get(parameterIndex);
729 			if (checksOfMethodParameter == null) return;
730 
731 			checksOfMethodByParameter.remove(parameterIndex);
732 		}
733 	}
734 
735 	public void clearMethodPostChecks(final Method method)
736 	{
737 		synchronized (checksForMethodsPostExcecution)
738 		{
739 			checksForMethodsPostExcecution.remove(method);
740 		}
741 	}
742 
743 	public void clearMethodPreChecks(final Method method)
744 	{
745 		synchronized (checksForMethodsPreExecution)
746 		{
747 			checksForMethodsPreExecution.remove(method);
748 		}
749 	}
750 
751 	public void clearMethodReturnValueChecks(final Method method)
752 	{
753 		synchronized (checksForMethodReturnValues)
754 		{
755 			checksForMethodReturnValues.remove(method);
756 			constrainedMethods.remove(method);
757 			constrainedStaticMethods.remove(method);
758 		}
759 	}
760 
761 	public void clearObjectChecks()
762 	{
763 		synchronized (checksForObject)
764 		{
765 			checksForObject.clear();
766 		}
767 	}
768 
769 	public void removeConstructorParameterCheckExclusions(final Constructor< ? > constructor, final int parameterIndex,
770 			final CheckExclusion... exclusions)
771 	{
772 		synchronized (checksForConstructorParameters)
773 		{
774 			// retrieve the currently registered checks for all parameters of the specified method
775 			final Map<Integer, ParameterChecks> checksOfConstructorByParameter = checksForConstructorParameters.get(constructor);
776 			if (checksOfConstructorByParameter == null) return;
777 
778 			// retrieve the checks for the specified parameter
779 			final ParameterChecks checksOfConstructorParameter = checksOfConstructorByParameter.get(parameterIndex);
780 			if (checksOfConstructorParameter == null) return;
781 
782 			for (final CheckExclusion exclusion : exclusions)
783 				checksOfConstructorParameter.checkExclusions.remove(exclusion);
784 
785 			if (checksOfConstructorParameter.isEmpty()) checksOfConstructorByParameter.remove(parameterIndex);
786 		}
787 	}
788 
789 	public void removeConstructorParameterChecks(final Constructor< ? > constructor, final int parameterIndex, final Check... checks)
790 	{
791 		synchronized (checksForConstructorParameters)
792 		{
793 			// retrieve the currently registered checks for all parameters of the specified method
794 			final Map<Integer, ParameterChecks> checksOfConstructorByParameter = checksForConstructorParameters.get(constructor);
795 			if (checksOfConstructorByParameter == null) return;
796 
797 			// retrieve the checks for the specified parameter
798 			final ParameterChecks checksOfConstructorParameter = checksOfConstructorByParameter.get(parameterIndex);
799 			if (checksOfConstructorParameter == null) return;
800 
801 			for (final Check check : checks)
802 				checksOfConstructorParameter.checks.remove(check);
803 
804 			if (checksOfConstructorParameter.isEmpty()) checksOfConstructorByParameter.remove(parameterIndex);
805 		}
806 	}
807 
808 	public void removeFieldChecks(final Field field, final Check... checks)
809 	{
810 		synchronized (checksForFields)
811 		{
812 			final Set<Check> checksOfField = checksForFields.get(field);
813 
814 			if (checksOfField == null) return;
815 
816 			for (final Check check : checks)
817 				checksOfField.remove(check);
818 
819 			if (checksOfField.size() == 0)
820 			{
821 				checksForFields.remove(field);
822 				constrainedFields.remove(field);
823 				constrainedStaticFields.remove(field);
824 			}
825 		}
826 	}
827 
828 	public void removeMethodParameterCheckExclusions(final Method method, final int parameterIndex, final CheckExclusion... exclusions)
829 	{
830 		if (parameterIndex < 0 || parameterIndex > method.getParameterTypes().length)
831 			throw new InvalidConfigurationException("ParameterIndex is out of range");
832 
833 		synchronized (checksForMethodParameters)
834 		{
835 			// retrieve the currently registered checks for all parameters of the specified method
836 			final Map<Integer, ParameterChecks> checksOfMethodByParameter = checksForMethodParameters.get(method);
837 			if (checksOfMethodByParameter == null) return;
838 
839 			// retrieve the checks for the specified parameter
840 			final ParameterChecks checksOfMethodParameter = checksOfMethodByParameter.get(parameterIndex);
841 			if (checksOfMethodParameter == null) return;
842 
843 			for (final CheckExclusion exclusion : exclusions)
844 				checksOfMethodParameter.checkExclusions.remove(exclusion);
845 
846 			if (checksOfMethodParameter.isEmpty()) checksOfMethodByParameter.remove(parameterIndex);
847 		}
848 	}
849 
850 	public void removeMethodParameterChecks(final Method method, final int parameterIndex, final Check... checks)
851 			throws InvalidConfigurationException
852 	{
853 		if (parameterIndex < 0 || parameterIndex > method.getParameterTypes().length)
854 			throw new InvalidConfigurationException("ParameterIndex is out of range");
855 
856 		synchronized (checksForMethodParameters)
857 		{
858 			// retrieve the currently registered checks for all parameters of the specified method
859 			final Map<Integer, ParameterChecks> checksOfMethodByParameter = checksForMethodParameters.get(method);
860 			if (checksOfMethodByParameter == null) return;
861 
862 			// retrieve the checks for the specified parameter
863 			final ParameterChecks checksOfMethodParameter = checksOfMethodByParameter.get(parameterIndex);
864 			if (checksOfMethodParameter == null) return;
865 
866 			for (final Check check : checks)
867 				checksOfMethodParameter.checks.remove(check);
868 
869 			if (checksOfMethodParameter.isEmpty()) checksOfMethodByParameter.remove(parameterIndex);
870 		}
871 	}
872 
873 	public void removeMethodPostChecks(final Method method, final PostCheck... checks)
874 	{
875 		synchronized (checksForMethodsPostExcecution)
876 		{
877 			final Set<PostCheck> checksforMethod = checksForMethodsPostExcecution.get(method);
878 
879 			if (checksforMethod == null) return;
880 
881 			for (final PostCheck check : checks)
882 				checksforMethod.remove(check);
883 
884 			if (checksforMethod.size() == 0) checksForMethodsPostExcecution.remove(method);
885 		}
886 	}
887 
888 	public void removeMethodPreChecks(final Method method, final PreCheck... checks)
889 	{
890 		synchronized (checksForMethodsPreExecution)
891 		{
892 			final Set<PreCheck> checksforMethod = checksForMethodsPreExecution.get(method);
893 
894 			if (checksforMethod == null) return;
895 
896 			for (final PreCheck check : checks)
897 				checksforMethod.remove(check);
898 
899 			if (checksforMethod.size() == 0) checksForMethodsPreExecution.remove(method);
900 		}
901 	}
902 
903 	public void removeMethodReturnValueChecks(final Method method, final Check... checks)
904 	{
905 		synchronized (checksForMethodReturnValues)
906 		{
907 			final Set<Check> checksOfMethod = checksForMethodReturnValues.get(method);
908 
909 			if (checksOfMethod == null) return;
910 
911 			for (final Check check : checks)
912 				checksOfMethod.remove(check);
913 
914 			if (checksOfMethod.size() == 0)
915 			{
916 				checksForMethodReturnValues.remove(method);
917 				constrainedMethods.remove(method);
918 				constrainedStaticMethods.remove(method);
919 			}
920 		}
921 	}
922 
923 	public void removeObjectChecks(final Check... checks)
924 	{
925 		synchronized (checksForObject)
926 		{
927 			for (final Check check : checks)
928 				checksForObject.remove(check);
929 		}
930 	}
931 }