aboutsummaryrefslogtreecommitdiffstats
path: root/docs/sandbox/common/declares/Declares.java
blob: 42fbcf4a24e1d46a9d0605e445eaa6650b92dca7 (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
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 
}

// 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);
  }
}
}
*/