package declares;
import com.company.app.*;
import java.rmi.RemoteException;
import java.io.IOException;
/**
* @author Wes Isberg
*/
aspect A {
// START-SAMPLE declares-threadFactoryRequired Error when not using Thread factory
/** signal error if Thread constructor called outside our Thread factory */
declare error : call(Thread+.new(..)) && within(com.company..*)
&& !withincode(Thread com.company.lib.Factory.makeThread(..)) :
"constructing threads prohibited - use Factory.makeThread(..)";
// END-SAMPLE declares-threadFactoryRequired
}
// XXX platform invariants: J2ME, J2EE, AWT thread, ...
/* @author Wes Isberg */
aspect TypeConstraints {
// START-SAMPLE declares-typeConstraints Using declare to enforce type constraints
protected interface SoughtException {}
// XXX ajc broken here?
/**
* Require that any SoughtException implementation be
* a subclass of Throwable. This picks out the mistake
* of declaring SoughtException a parent of something
* that is not an exception at all.
*/
declare error : staticinitialization(SoughtException+)
&& ! staticinitialization(SoughtException)
&& ! staticinitialization(Throwable+) :
"all SoughtException must be subclasses of Throwable";
// END-SAMPLE declares-typeConstraints
}
// START-SAMPLE declares-exceptionSpelunking Using declare warning to find Exception-related code
/**
* List AppException catch blocks and callers as a way
* of investigating a possibly-large code base.
*/
aspect SeekAppExceptions {
pointcut withinScope() : within(com.company..*);
/**
* Find calls to stuff that throws AppException.
*/
declare warning : withinScope() &&
(call(* *(..) throws AppException+)
|| call(new(..) throws AppException+)) :
"fyi, another call to something that can throw IOException";
/**
* Find catch clauses handling AppException
*/
declare warning : withinScope() && handler(AppException+):
"fyi, code that handles AppException";
}
// END-SAMPLE declares-exceptionSpelunking
/** @author Jim Hugunin, Wes Isberg */
class RuntimeRemoteException extends RuntimeException {
RuntimeRemoteException(RemoteException e) {}
}
// XXX untested sample declares-softenRemoteException
// START-SAMPLE declares-softenRemoteException
/**
* Convert RemoteExceptions to RuntimeRemoteException
* and log them. Enable clients that don't handle
* RemoteException.
*/
aspect HandleRemoteException {
/**
* Declare RemoteException soft to enable use by clients
* that are not declared to handle RemoteException.
*/
declare soft: RemoteException: throwsRemoteException();
/**
* Pick out join points to convert RemoteException to
* RuntimeRemoteException.
* This implementation picks out
* execution of any method declared to throw RemoteException
* in our library.
*/
pointcut throwsRemoteException(): within(com.company.lib..*)
&& execution(* *(..) throws RemoteException+);
/**
* This around advice converts RemoteException to
* RuntimeRemoteException at all join points picked out
* by throwsRemoteException()
.
* That means *no* RemoteException will be thrown from
* this join point, and thus that none will be converted
* by the AspectJ runtime to SoftException
.
*/
Object around(): throwsRemoteException() {
try {
return proceed();
} catch (RemoteException re) {
re.printStackTrace(System.err);
throw new RuntimeRemoteException(re);
}
}
}
//END-SAMPLE declares-softenRemoteException
/*
XXX another declare-soft example from Jim:
aspect A {
pointcut check():
within(com.foo.framework.persistence.*) &&
executions(* *(..));
declare soft: SQLException: check();
after () throwing (SQLException sqlex): check() {
if (sql.getSQLCode().equals("SZ001")) {
throw new AppRuntimeException("Non-fatal Database error occurred.",
"cache refresh failure", sqlex);
} else {
throw new AppFatalRuntimeException(
"Database error occurred - contact support", sqlex);
}
}
}
*/