diff options
Diffstat (limited to 'docs/sandbox/common')
-rw-r--r-- | docs/sandbox/common/caching/Caching.java | 0 | ||||
-rw-r--r-- | docs/sandbox/common/com/company/app/AppException.java | 11 | ||||
-rw-r--r-- | docs/sandbox/common/com/company/app/Main.java | 40 | ||||
-rw-r--r-- | docs/sandbox/common/com/company/lib/Factory.java | 14 | ||||
-rw-r--r-- | docs/sandbox/common/company.lst | 2 | ||||
-rw-r--r-- | docs/sandbox/common/declares/Declares.java | 140 | ||||
-rw-r--r-- | docs/sandbox/common/language/Context.java | 70 | ||||
-rw-r--r-- | docs/sandbox/common/language/ControlFlow.java | 43 | ||||
-rw-r--r-- | docs/sandbox/common/language/Initialization.java | 95 | ||||
-rw-r--r-- | docs/sandbox/common/libraries/PointcutLibraryTest.java | 95 | ||||
-rw-r--r-- | docs/sandbox/common/tracing/Logging.java | 28 | ||||
-rw-r--r-- | docs/sandbox/common/tracing/TraceJoinPoints.java | 132 | ||||
-rw-r--r-- | docs/sandbox/common/tracing/TraceJoinPointsBase.java | 53 | ||||
-rw-r--r-- | docs/sandbox/common/tracing/TraceMyJoinPoints.java | 17 |
14 files changed, 740 insertions, 0 deletions
diff --git a/docs/sandbox/common/caching/Caching.java b/docs/sandbox/common/caching/Caching.java new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/docs/sandbox/common/caching/Caching.java diff --git a/docs/sandbox/common/com/company/app/AppException.java b/docs/sandbox/common/com/company/app/AppException.java new file mode 100644 index 000000000..aa23eeff8 --- /dev/null +++ b/docs/sandbox/common/com/company/app/AppException.java @@ -0,0 +1,11 @@ + +package com.company.app; + +public class AppException extends Exception { + public AppException() { + super(); + } + public AppException(String s) { + super(s); + } +}
\ No newline at end of file diff --git a/docs/sandbox/common/com/company/app/Main.java b/docs/sandbox/common/com/company/app/Main.java new file mode 100644 index 000000000..8d04c0ec9 --- /dev/null +++ b/docs/sandbox/common/com/company/app/Main.java @@ -0,0 +1,40 @@ + +package com.company.app; + +import java.util.Arrays; +import org.aspectj.lang.SoftException; + +public class Main implements Runnable { + public static void main(String[] argList) { + new Main().runMain(argList); + } + + String[] input; + + void spawn() { + new Thread(this, toString()).start(); // KEEP CE 15 declares-factory + } + + public void runMain(String[] argList) { + this.input = argList; + run(); + } + + public void run() { + String[] input = this.input; + String s = ((null == input) || (0 == input.length)) + ? "[]" + : Arrays.asList(input).toString(); + System.out.println("input: " + s); + try { + doDangerousThings(); // KEEP CW 30 declares-exceptionSpelunking + } catch (AppException e) { // KEEP CW 31 declares-exceptionSpelunking + e.printStackTrace(System.err); + } + } + + private void doDangerousThings() throws AppException { // KEEP CW 38 + + } + +}
\ No newline at end of file diff --git a/docs/sandbox/common/com/company/lib/Factory.java b/docs/sandbox/common/com/company/lib/Factory.java new file mode 100644 index 000000000..3abb207c9 --- /dev/null +++ b/docs/sandbox/common/com/company/lib/Factory.java @@ -0,0 +1,14 @@ + +package com.company.lib; + +public class Factory { + + public static Thread makeThread(Runnable runnable, String name) { + class MyThread extends Thread { + MyThread(Runnable runnable, String name) { + super(runnable, name); + } + } + return new MyThread(runnable, name); + } +}
\ No newline at end of file diff --git a/docs/sandbox/common/company.lst b/docs/sandbox/common/company.lst new file mode 100644 index 000000000..64c4786f7 --- /dev/null +++ b/docs/sandbox/common/company.lst @@ -0,0 +1,2 @@ +com/company/app/*.java +com/company/lib/*.java diff --git a/docs/sandbox/common/declares/Declares.java b/docs/sandbox/common/declares/Declares.java new file mode 100644 index 000000000..4f763440b --- /dev/null +++ b/docs/sandbox/common/declares/Declares.java @@ -0,0 +1,140 @@ + +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 + +} + +/* @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 Using declare to enforce type constraints +} + +// 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 <code>throwsRemoteException()</code>. + * That means *no* RemoteException will be thrown from + * this join point, and thus that none will be converted + * by the AspectJ runtime to <code>SoftException</code>. + */ + 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); + } +} +} +*/ diff --git a/docs/sandbox/common/language/Context.java b/docs/sandbox/common/language/Context.java new file mode 100644 index 000000000..f0021a28a --- /dev/null +++ b/docs/sandbox/common/language/Context.java @@ -0,0 +1,70 @@ + +package language; + +public class Context { + public static void main(String[] argList) { + new C().run(); + } +} + +class C { + static int MAX = 2; + int i; + C() { + i = 1; + } + public void run() { + try { + more(); + } catch (MoreError e) { + // log but continue + System.out.println(e.getMessage()); + } + } + + private void more() { + i++; + if (i >= MAX) { + i = 0; + throw new MoreError(); + } + } + static class MoreError extends Error { + MoreError() { + super("was too much!"); + } + } +} + +/** @author Erik Hilsdale, Wes Isberg */ +aspect A { + + // START-SAMPLE language-fieldSetContext Check input and result for a field set. + /** + * Check input and result for a field set. + */ + void around(int input, C targ) : set(int C.i) + && args(input) && target(targ) { + String m = "setting C.i=" + targ.i + " to " + input; + System.out.println(m); + proceed(input, targ); + if (targ.i != input) { + throw new Error("expected " + input); + } + } + // END-SAMPLE language-fieldSetContext + + // START-SAMPLE language-handlerContext Log exception being handled + /** + * Log exception being handled + */ + before (C.MoreError e) : handler(C.MoreError) + && args(e) && within(C) { + System.out.println("handling " + e); + } + // END-SAMPLE language-handlerContext + + // See Initialization.java for constructor call, + // constructor execution, and {pre}-initialization + +}
\ No newline at end of file diff --git a/docs/sandbox/common/language/ControlFlow.java b/docs/sandbox/common/language/ControlFlow.java new file mode 100644 index 000000000..d832259db --- /dev/null +++ b/docs/sandbox/common/language/ControlFlow.java @@ -0,0 +1,43 @@ + +package language; + +public class ControlFlow { + public static void main(String[] argList) { + Fact.factorial(6); + } +} + +class Fact { + static int factorial(int i) { + if (i < 0) { + throw new IllegalArgumentException("negative: " + i); + } + if (i > 100) { + throw new IllegalArgumentException("big: " + i); + } + return (i == 0 ? 1 : i * factorial(i-1)); + } +} + +/** + * Demonstrate recursive calls. + * @author Erik Hilsdale + */ +aspect LogFactorial { + // START-SAMPLE language-cflowRecursionBasic Pick out latest and original recursive call + /** call to factorial, with argument */ + pointcut f(int i) : call(int Fact.factorial(int)) && args(i); + + /** print most-recent recursive call */ + before(int i, final int j) : f(i) && cflowbelow(f(j)) { + System.err.println(i + "-" + j); + } + + /** print initial/topmost recursive call */ + before(int i, final int j) : f(i) + && cflowbelow(cflow(f(j)) && !cflowbelow(f(int))) { + System.err.println(i + "@" + j); + } + // END-SAMPLE language-cflowRecursionBasic +} + diff --git a/docs/sandbox/common/language/Initialization.java b/docs/sandbox/common/language/Initialization.java new file mode 100644 index 000000000..46d3ec872 --- /dev/null +++ b/docs/sandbox/common/language/Initialization.java @@ -0,0 +1,95 @@ + +package language; + +public class Initialization { + public static void main(String[] argList) { + Thing thing = new Thing(); + if (12 != thing.counter) { + System.err.println("expected 12, got " + thing.counter); + } + thing = new Thing(20); + if (32 != thing.counter) { + System.err.println("expected 32, got " + thing.counter); + } + thing = new AnotherThing(); + if (2 != thing.counter) { + System.err.println("expected 2, got " + thing.counter); + } + thing = new AnotherThing(20); + if (23 != thing.counter) { + System.err.println("expected 23, got " + thing.counter); + } + } +} +/** @author Erik Hilsdale, Wes Isberg */ + +// START-SAMPLE language-initialization Understanding object creation join points +/* + * To work with an object right when it is constructed, + * understand the differences between the join points for + * constructor call, constructor execution, and initialization. + */ +class Thing { + int counter; + Thing() { + this(1); + } + Thing(int value) { + counter = value; + } +} + +class AnotherThing extends Thing { + AnotherThing() { + super(); + } + + AnotherThing(int i) { + super(++i); + } +} + +aspect A { + /** + * After any call to any constructor, fix up the thing. + * In AspectJ 1.1, this only affects callers in the input + * classes or source files, but not super calls. + */ + after() returning (Thing thing): + call(Thing.new(..)) { + postInitialize(thing); + } + + /** + * After executing the int constructor, fix up the thing. + * This works regardless of how the constructor was called + * (by outside code or by super), but only for the + * specified constructors. + */ + after() returning (Thing thing): execution(Thing.new(int)) { + thing.counter++; + } + + /** + * DANGER -- BAD!! Before executing the int constructor, + * this uses the target object, which is not constructed. + */ + before (Thing thing): this(thing) && execution(Thing.new(int)) { + // thing.counter++; // DANGER!! thing not constructed yet. + } + + /** + * This advises all Thing constructors in one join point, + * even if they call each other with this(). + */ + after(Thing thing) returning: this(thing) + && initialization(Thing.new(..)) { + thing.counter++; + } + + protected void postInitialize(Thing thing) { + thing.counter += 10; + } +} +//END-SAMPLE language-initialization + diff --git a/docs/sandbox/common/libraries/PointcutLibraryTest.java b/docs/sandbox/common/libraries/PointcutLibraryTest.java new file mode 100644 index 000000000..e110c7ced --- /dev/null +++ b/docs/sandbox/common/libraries/PointcutLibraryTest.java @@ -0,0 +1,95 @@ +package libraries; + +/** @author Wes Isberg */ +public class PointcutLibraryTest { + public static void main(String[] a) { + new Test().run(); + } +} + +class Test { + public Test() {} + public void run(){ prun(); } + private void prun() { + System.out.println("Test.prun()"); + } +} + +// START-SAMPLE library-classPointcutLibrary Defining library pointcuts in a class +/** private default implementation of library */ +class PrivatePointcutLibrary { + pointcut adviceCflow() : cflow(adviceexecution()); + pointcut publicCalls() : call(public * *(..)) + && !adviceCflow() + ; +} + +/** public interface for library */ +class PointcutLibrary extends PrivatePointcutLibrary { +} + +// ---- different clients of the library + +/** client by external reference to library */ +aspect ExternalClientOfLibrary { + before() : PointcutLibrary.publicCalls() { + System.out.println("XCL: " + + thisJoinPointStaticPart); + } +} + +/** use library by inheriting scope in aspect */ +aspect AEL extends PointcutLibrary { + before() : publicCalls() { + System.out.println("AEL: " + + thisJoinPointStaticPart); + } +} + +/** use library by inheriting scope in class */ +class CEL extends PointcutLibrary { + static aspect A { + before() : publicCalls() { + System.out.println("CEL: " + + thisJoinPointStaticPart); + } + } +} + +/** more clients by inheritance */ +aspect CELSubAspect extends CEL { + before() : publicCalls() { + System.out.println("CSA: " + + thisJoinPointStaticPart); + } +} + + +// ---- redefining library pointcuts + +//-- affect all clients of PointcutLibrary +// test: XCL advises Test() +class VendorPointcutLibrary extends PrivatePointcutLibrary { + /** add calls to public constructors */ + pointcut publicCalls() : PrivatePointcutLibrary.publicCalls() + || (call(public new(..)) && !adviceCflow()); + static aspect A { + declare parents: + PointcutLibrary extends VendorPointcutLibrary; + } +} + +//-- only affect CEL, subtypes, & references thereto +// test: CSA does not advise call(* println(String)) +// test: CSA advises call(* prun()) +class CPlus extends PointcutLibrary { + /** add calls to private methods, remove calls to java..* */ + pointcut publicCalls() : (PointcutLibrary.publicCalls() + || (call(private * *(..)) && !adviceCflow())) + && (!(call(* java..*.*(..)) || call(java..*.new(..)))); + static aspect A { + declare parents: CEL extends CPlus; + } +} +// END-SAMPLE library-classPointcutLibrary + diff --git a/docs/sandbox/common/tracing/Logging.java b/docs/sandbox/common/tracing/Logging.java new file mode 100644 index 000000000..349abb235 --- /dev/null +++ b/docs/sandbox/common/tracing/Logging.java @@ -0,0 +1,28 @@ + +package tracing; + +import org.aspectj.lang.Signature; + +/** + * @author Wes Isberg + */ +aspect A { + // START-SAMPLE tracing-simpleTiming Record time to execute public methods + /** record time to execute my public methods */ + Object around() : execution(public * com.company..*.* (..)) { + long start = System.currentTimeMillis(); + try { + return proceed(); + } finally { + long end = System.currentTimeMillis(); + recordTime(start, end, + thisJoinPointStaticPart.getSignature()); + } + } + // implement recordTime... + // END-SAMPLE tracing-simpleTiming + + void recordTime(long start, long end, Signature sig) { + // to implement... + } +} diff --git a/docs/sandbox/common/tracing/TraceJoinPoints.java b/docs/sandbox/common/tracing/TraceJoinPoints.java new file mode 100644 index 000000000..fd42a0fde --- /dev/null +++ b/docs/sandbox/common/tracing/TraceJoinPoints.java @@ -0,0 +1,132 @@ + +// START-SAMPLE tracing-traceJoinPoints Trace join points executed to log +/* TraceJoinPoints.java */ + +package tracing; + +import org.aspectj.lang.*; +import org.aspectj.lang.reflect.*; +import java.io.*; + +/** + * Print join points being executed in context to a log.xml file. + * To use this, define the abstract pointcuts in a subaspect. + * @author Jim Hugunin, Wes Isberg + */ +public abstract aspect TraceJoinPoints + extends TraceJoinPointsBase { + + // abstract protected pointcut entry(); + + PrintStream out; + int logs = 0; + int depth = 0; + boolean terminal = false; + + /** + * Emit a message in the log, e.g., + * <pre>TraceJoinPoints tjp = TraceJoinPoints.aspectOf(); + * if (null != tjp) tjp.message("Hello, World!");</pre> + */ + public void message(String s) { + out.println("<message>" + prepareMessage(s) + "</message>"); + } + + protected void startLog() { + makeLogStream(); + } + + protected void completeLog() { + closeLogStream(); + } + + protected void logEnter(JoinPoint.StaticPart jp) { + if (terminal) out.println(">"); + indent(depth); + out.print("<" + jp.getKind()); + writeSig(jp); + writePos(jp); + + depth += 1; + terminal = true; + } + + protected void logExit(JoinPoint.StaticPart jp) { + depth -= 1; + if (terminal) { + getOut().println("/>"); + } else { + indent(depth); + getOut().println("</" + jp.getKind() + ">"); + } + terminal = false; + } + + protected PrintStream getOut() { + if (null == out) { + String m = "not in the control flow of entry()"; + throw new IllegalStateException(m); + } + return out; + } + + protected void makeLogStream() { + try { + String name = "log" + logs++ + ".xml"; + out = new PrintStream(new FileOutputStream(name)); + } catch (IOException ioe) { + out = System.err; + } + } + + protected void closeLogStream() { + PrintStream out = this.out; + if (null != out) { + out.close(); + // this.out = null; + } + } + + /** @return input String formatted for XML */ + protected String prepareMessage(String s) { // XXX unimplemented + return s; + } + + void message(String sink, String s) { + if (null == sink) { + message(s); + } else { + getOut().println("<message sink=" + quoteXml(sink) + + " >" + prepareMessage(s) + "</message>"); + } + } + + void writeSig(JoinPoint.StaticPart jp) { + PrintStream out = getOut(); + out.print(" sig="); + out.print(quoteXml(jp.getSignature().toShortString())); + } + + void writePos(JoinPoint.StaticPart jp) { + SourceLocation loc = jp.getSourceLocation(); + if (loc == null) return; + PrintStream out = getOut(); + + out.print(" pos="); + out.print(quoteXml(loc.getFileName() + + ":" + loc.getLine() + + ":" + loc.getColumn())); + } + + protected String quoteXml(String s) { // XXX weak + return "\"" + s.replace('<', '_').replace('>', '_') + "\""; + } + + protected void indent(int i) { + PrintStream out = getOut(); + while (i-- > 0) out.print(" "); + } +} +// END-SAMPLE tracing-traceJoinPoints + +
\ No newline at end of file diff --git a/docs/sandbox/common/tracing/TraceJoinPointsBase.java b/docs/sandbox/common/tracing/TraceJoinPointsBase.java new file mode 100644 index 000000000..d06423001 --- /dev/null +++ b/docs/sandbox/common/tracing/TraceJoinPointsBase.java @@ -0,0 +1,53 @@ + +// START-SAMPLE tracing-traceJoinPoints Trace join points executed +/* TraceJoinPointsBase.java */ + +package tracing; + +import org.aspectj.lang.JoinPoint; + +/** + * Trace join points being executed in context. + * To use this, define the abstract members in a subaspect. + * <b>Warning</b>: this does not trace join points that do not + * support after advice. + * @author Jim Hugunin, Wes Isberg + */ +abstract aspect TraceJoinPointsBase { + // this line is for AspectJ 1.1 + // for Aspectj 1.0, use "TraceJoinPointsBase dominates * {" + declare precedence : TraceJoinPointsBase, *; + + abstract protected pointcut entry(); + + protected pointcut exit(): call(* java..*.*(..)); + + final pointcut start(): entry() && !cflowbelow(entry()); + + final pointcut trace(): cflow(entry()) + && !cflowbelow(exit()) && !within(TraceJoinPointsBase+); + + private pointcut supportsAfterAdvice() : !handler(*) + && !preinitialization(new(..)); + + before(): start() { startLog(); } + + before(): trace() && supportsAfterAdvice(){ + logEnter(thisJoinPointStaticPart); + } + + after(): trace() && supportsAfterAdvice() { + logExit(thisJoinPointStaticPart); + } + + after(): start() { completeLog(); } + + abstract protected void logEnter(JoinPoint.StaticPart jp); + abstract protected void logExit(JoinPoint.StaticPart jp); + abstract protected void startLog(); + abstract protected void completeLog(); +} + +// END-SAMPLE tracing-traceJoinPoints + +
\ No newline at end of file diff --git a/docs/sandbox/common/tracing/TraceMyJoinPoints.java b/docs/sandbox/common/tracing/TraceMyJoinPoints.java new file mode 100644 index 000000000..a5aa686d6 --- /dev/null +++ b/docs/sandbox/common/tracing/TraceMyJoinPoints.java @@ -0,0 +1,17 @@ + + +// START-SAMPLE tracing-traceJoinPoints Trace to log join points executed by main method +/* TraceMyJoinPoints.java */ + +package tracing; + +import com.company.app.Main; + +/** + * Trace all join points in company application. + * @author Jim Hugunin, Wes Isberg + */ +aspect TraceMyJoinPoints extends TraceJoinPoints { + protected pointcut entry() : execution(void Main.runMain(String[])); +} +// END-SAMPLE tracing-traceJoinPoints |