summaryrefslogtreecommitdiffstats
path: root/tests/tracing/TraceJoinPoints.java
blob: 095172c289770c048a31965d86c48ba28f6cb119 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import org.aspectj.lang.*;
import org.aspectj.lang.reflect.*;
import java.io.*;

/**
 * Produces an XML representation of all of the join points in a program
 * within the control-flow of those points matching <code>entry</code>.
 *
 * To use this, extend this aspect and fill in an appropriate value for
 * <code>entry</code>.
 */
public abstract aspect TraceJoinPoints dominates * {
    /**
     * The join points which mark the entry of the traced control-flow.
     * To trace all command-line programs, set this to:
     *     <pre>call(public static void main(String[]));</pre>
     */
    protected abstract pointcut entry();

    /**
     * Join points which mark an exit from the control-flow.  Use this
     * to exclude parts of the call-graph that you're not interested in.
     * The default value matches the current implementation limitation
     * (in ajc-1.0) that join points within system libraries are not
     * visible.
     */
    protected pointcut exit(): call(* java..*.*(..));

    final pointcut start(): entry() && !cflowbelow(entry());

    final pointcut trace():
        cflow(entry()) && !cflowbelow(exit()) && !within(TraceJoinPoints+);

    before(): start() { makeLogStream(); }

    before(): trace() { logEnter(thisJoinPointStaticPart); }
    after(): trace() { logExit(thisJoinPointStaticPart); }

    after(): start() { closeLogStream(); }


    PrintStream out;
    int logs = 0;
    protected void makeLogStream() {
        try {
            out = new PrintStream(new FileOutputStream("log" + logs++ + ".xml"));
        } catch (IOException ioe) {
            out = System.err;
        }
    }

    protected void closeLogStream() {
        out.close();
    }


    int depth = 0;
    boolean terminal = false;
    protected void logEnter(JoinPoint.StaticPart jp) {
        if (terminal) out.println(">");
        indent(depth);
        out.print("<" + jp.getKind());
        writeSig(jp);
        writePos(jp);

        depth += 1;
        terminal = true;
    }

    void writeSig(JoinPoint.StaticPart jp) {
        out.print(" sig=");
        out.print(quoteXml(jp.getSignature().toShortString()));
    }

    void writePos(JoinPoint.StaticPart jp) {
        SourceLocation loc = jp.getSourceLocation();
        if (loc == null) return;

        out.print(" pos=");
        out.print(quoteXml(loc.getFileName() +
                           ":" + loc.getLine() +
                           ":" + loc.getColumn()));
    }

    String quoteXml(String s) {
        return "\"" + s.replace('<', '_').replace('>', '_') + "\"";
    }

    protected void logExit(JoinPoint.StaticPart jp) {
        depth -= 1;
        if (terminal) {
            out.println("/>");
        } else {
            indent(depth);
            out.println("</" + jp.getKind() + ">");
        }
        terminal = false;
    }

    void indent(int i) {
        while (i-- > 0) out.print("  ");
    }
}