All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.check.runtime.AbstractNullPointerTrap.aj Maven / Gradle / Ivy

Go to download

PatternTesting Check.RT (patterntesting-check-rt) provides different runtime checks of known anti patterns (like using null values as arguments or return values) but provides also a test framework for better testing.

There is a newer version: 2.4.0
Show newest version
/**
 * $Id: AbstractNullPointerTrap.aj,v 1.1 2011/12/22 17:15:11 oboehm Exp $
 *
 * Copyright (c) 2007 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 11.12.2007 by oliver ([email protected])
 */
package patterntesting.check.runtime;

import java.lang.annotation.Annotation;

import org.apache.commons.logging.Log;
import org.aspectj.lang.*;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.aspectj.lang.reflect.ConstructorSignature;

import patterntesting.annotation.check.runtime.MayBeNull;
import patterntesting.runtime.util.*;

/**
 * In the AbstractNullTest aspect we log only if a null value is given to a
 * method. The NullPointerTrap here is much stricter: it requires
 * that
 * 
    *
  • no null value is given
  • *
  • null as return value is forbidden
  • *
  • if one of this requirements are hurt an AssertionExecption is * thrown. *
  • *
* As in AbstractNullTest you can define exceptions from these strict rules * by defining the abstract pointcuts applicationCode, * nullArgsAllowed and mayReturnNull. * * This aspect is intended more for finding bugs in the test phase whereas * AbstractNullTest can be also used during production because it logs only * the problematic calls with a null parameter. * * @author oliver * @since 11.12.2007 * @version $Revision: 1.1 $ */ public abstract aspect AbstractNullPointerTrap { protected static final boolean assertEnabled = Assertions.areEnabled(); /** * To get the aspect specific logger. * @return the logger */ public abstract Log getLog(); /** * Specify what the application code is that should be subject to the * pattern test. *
* Ex: pointcut applicationCode(): within(patterntesting.sample.*) */ public abstract pointcut applicationCode(); /** * Specify which code is allowed to have null parameters. *
* Ex: execution(@NullArgsAllowed * *..*(*, ..)) * || execution(@NullArgsAllowed *..new(*, ..)) */ public abstract pointcut nullArgsAllowed(); /** * Specify which methods may return null. * Some methods (like find methods or getters) may return a null value. *
* Ex: execution(@MayReturnNull Object+ *..*(..)) */ public abstract pointcut mayReturnNull(); /** * Addresses all methods (or constructors) with at least one argument which * should not be given as null parameter. * For performance reason this is limited only to public methods * (or constructors) */ pointcut invalidNullParameter() : (execution(public * *..*(*, ..)) || execution(public *..new(*, ..))) && applicationCode() && !nullArgsAllowed() && !within(*NullPointerTrap); /** * If a (null) parameter is detected something is wrong with the * application code. Inner classes will be skipped because they are * handled different by the compiler (for private static inner classes * it adds an additional argument for the default constructor. But this * additional argument is always null). */ @SuppressAjWarnings({"adviceDidNotMatch"}) before() : invalidNullParameter() { if (!assertEnabled) { return; } Signature sig = thisJoinPoint.getSignature(); if ((sig instanceof ConstructorSignature) && (JoinPointHelper.isInnerClass(sig))) { if (getLog().isTraceEnabled()) { getLog().trace("check for " + sig + " is skipped (inner class)"); } return; } Annotation[][] paramAnnotations = JoinPointHelper .getParameterAnnotations(thisJoinPoint); assertArgsNotNull(thisJoinPoint, paramAnnotations); } /** * To check all non void methods if returns a null value we first define * the pointcut here. * For performance reason this is limited to public methods. */ private pointcut nonVoidMethods() : execution(public Object+ *..*(..)) && applicationCode() && !mayReturnNull() && !within(*NullPointerTrap); /** * A 'null' as return value is often an indication that something is wrong * (otherwise an exception should be thrown) */ @SuppressAjWarnings({"adviceDidNotMatch"}) after() returning(Object returned) : nonVoidMethods() { assert returned != null : thisJoinPoint.getSignature() + " returns null!"; } ///// some local helper /////////////////////////////////////////////// private static void assertArgsNotNull(final JoinPoint joinPoint, Annotation[][] paramAnnotations) { Object[] args = joinPoint.getArgs(); for (int i = 0; i < args.length; i++) { if ((args[i] == null) && !hasMayBeNullAnnotation(paramAnnotations[i])) { assert args[i] != null : "arg" + i + " is null"; } } } private static boolean hasMayBeNullAnnotation(final Annotation[] annotations) { if (annotations == null) { return false; } for (Annotation annotation : annotations) { if (annotation instanceof MayBeNull) { return true; } } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy