KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > ch > ethz > prose > crosscut > SignaturePattern


1 //
2
// This file is part of the prose package.
3
//
4
// The contents of this file are subject to the Mozilla Public License
5
// Version 1.1 (the "License"); you may not use this file except in
6
// compliance with the License. You may obtain a copy of the License at
7
// http://www.mozilla.org/MPL/
8
//
9
// Software distributed under the License is distributed on an "AS IS" basis,
10
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
// for the specific language governing rights and limitations under the
12
// License.
13
//
14
// The Original Code is prose.
15
//
16
// The Initial Developer of the Original Code is Andrei Popovici. Portions
17
// created by Andrei Popovici are Copyright (C) 2002 Andrei Popovici.
18
// All Rights Reserved.
19
//
20
// Contributor(s):
21
// $Id: SignaturePattern.java,v 1.2 2003/07/11 12:27:43 apopovic Exp $
22
// =====================================================================
23
//
24
// (history at end)
25
//
26

27 package ch.ethz.prose.crosscut;
28
29 // used packages
30
import java.lang.reflect.Method JavaDoc;
31 import java.lang.Class JavaDoc;
32
33
34 /** Every Crosscut contains a method to be executed when a join-point is hit.
35    * In the case of <code>MethodCut</code> objects, the SignaturePattern has three
36    * roles:
37    * <ul>
38    * <li> The pattern role: through a special signature, define matches for the
39    * target class, and for the parameters of the methods belonging to the target.
40    *
41    * <li> The method finder role: determine which method o of the crosscut
42    * must be ivoked upon a hit join-point.
43    *
44    * <li> The optimization role: to cathegorize the signature of the advice
45    * method, such that the subsequent execution of the advice method is efficient.
46    * The categorization is currently performed according to the <code>SIGNATURE__XXX</code>
47    * constants.
48    * </ul>
49    *
50    * @version $Revision: 1.2 $
51    * @author Andrei Popovici
52    */

53 public abstract
54 class SignaturePattern {
55
56
57     // work constants bit 3 bit 2
58
protected final static int WILDCARD_1 = 0x02;
59     protected final static int WILDCARD_2 = 0x04;
60     protected final static int CONCRETE_1= 0x08;
61     protected final static int CONCRETE_2= 0x01;
62
63     /// constants reflecting the cathegory of the signature of <code>methodObj</code>
64
protected static final int SIGNATURE__WILDCARD__WILDCARD = WILDCARD_1 | WILDCARD_2;
65     protected static final int SIGNATURE__WILDCARD__CONCRETE = WILDCARD_1 | CONCRETE_2;
66     protected static final int SIGNATURE__CONCRETE__WILDCARD = CONCRETE_1 | WILDCARD_2;
67     protected static final int SIGNATURE__CONCRETE__CONCRETE = CONCRETE_1 | CONCRETE_2;
68     protected static final int SIGNATURE__ARBITRARY = 0;
69     protected static final int SIGNATURE__EMPTY = 0x1000;
70
71     /** The signature cathegory of <code>methodObj</code>.
72      */

73     protected int signatureCathegory = SIGNATURE__ARBITRARY;
74
75     /** The method to be invoked upon reaching a joinpoint,
76      * or <code>null</code> if the enclosing
77      * Crosscut defines its own <code>adviceMethod</code>.
78      */

79     protected transient Method JavaDoc methodObj = null;
80
81     /** The signature of <code>methodObj</code>, equivalent to
82      * <code>methodObj.getParameterTypes()</code>. Present
83      * for efficiency reasons.
84      */

85     protected transient Class JavaDoc[] signature = null;
86
87     protected transient Class JavaDoc wildcardClass = null;
88
89
90
91     /**
92      * Return the number of arguments required by this advice.
93      */

94     protected int getLength()
95     {
96     return signature.length;
97     }
98
99     protected Class JavaDoc getReceiverType()
100     {
101     if (signature.length == 0)
102         return null;
103     else
104         return signature[0];
105     }
106   /** When no advice action is set, it returns true.
107      * If an advice action exists, it returns true
108      * if the pattern-matching signature acepts <code>actualClass</code>
109      * as a potential crosscut class.
110      *
111      */

112     protected boolean matchesTarget(Class JavaDoc actualClass)
113       {
114       if (signatureCathegory == SIGNATURE__EMPTY)
115           return true;
116       else
117           return isAssignable(actualClass, signature[0]);
118       }
119
120
121     protected boolean isAssignable(Class JavaDoc actualParameterType, Class JavaDoc formalParameterType) throws Error JavaDoc
122     {
123     if (Wildcard.class.isAssignableFrom(formalParameterType))
124       {
125         try
126           {
127         if (((Wildcard)formalParameterType.newInstance()).isAssignableFrom(actualParameterType))
128           return true;
129
130             // the Wilcard specification states that wildcard classes
131
// should have an emtpy default constructor. If they
132
// don't have: it is a RUNES IMPLEMENTATION ERROR
133
}
134         catch (IllegalAccessException JavaDoc noConstructor)
135           {
136         throw new Error JavaDoc(noConstructor.toString());
137           }
138         catch (InstantiationException JavaDoc wrongConstructor)
139           {
140         throw new Error JavaDoc(wrongConstructor.toString());
141           }
142         return false;
143       }
144     else if ( formalParameterType.isAssignableFrom(actualParameterType))
145       return true;
146     else
147       return false;
148       }
149
150
151     protected void initFromMethod(Class JavaDoc methodClass, String JavaDoc adviceName, Class JavaDoc wildcardClass,Class JavaDoc htop)
152     {
153
154     this.wildcardClass = wildcardClass;
155     initAdviceMethod(methodClass,adviceName,htop);
156     signature = methodObj.getParameterTypes();
157     initSignatureCathegory();
158     }
159
160     private void initAdviceMethod(Class JavaDoc methodClass,String JavaDoc adviceName,Class JavaDoc hierarchyTop)
161     {
162     int ambigousCnt = 0;
163     Method JavaDoc mObj = null;
164     Class JavaDoc crtClass = methodClass;
165
166
167     // look up a method with the name 'adviceName'; if such a method is found,
168
while (crtClass != null &&
169            !crtClass.equals(hierarchyTop) && // (e.g., crtClass != MethodCut)
170
hierarchyTop.isAssignableFrom(crtClass) && // (e.g., crtClass subclass of MethodCut)
171
mObj == null)
172     {
173         Method JavaDoc[] methods = crtClass.getDeclaredMethods();
174         ambigousCnt = 0;
175
176         // we have to select some method
177
// try to match a method with such a name
178

179         for (int i=0; i < methods.length; i++)
180         if ( methods[i].getName().equals(adviceName))
181             {
182             mObj = methods[i];
183             ambigousCnt++;
184             }
185
186         crtClass=crtClass.getSuperclass();
187     }
188
189     if (mObj == null)
190         throw new MissingInformationException("No advice action specified");
191     if (ambigousCnt > 1)
192         throw new MissingInformationException("Two advice methods detected. Ambigous advice specification");
193
194     try
195         {
196         mObj.setAccessible(true);
197         }
198     catch (SecurityException JavaDoc opaqueCrosscut)
199         {
200           // this is not very likely to ocurr
201
}
202
203     methodObj = mObj;
204       }
205
206     private void initSignatureCathegory()
207       {
208     Method JavaDoc m = methodObj;
209         int optimization = SIGNATURE__ARBITRARY;
210         Class JavaDoc[] adviceParamTypes = m.getParameterTypes();
211
212     if (adviceParamTypes.length == 0)
213         {
214         signatureCathegory = SIGNATURE__EMPTY;
215         return;
216         }
217
218         // figure out whether the receiver is a wildcard
219
if (ANY.class.isAssignableFrom(adviceParamTypes[0]))
220       optimization |= WILDCARD_1;
221     else
222       optimization |= CONCRETE_1;
223
224
225     // figure out whether *all* parameters are wildcard
226
boolean restIsWildcard = true;
227     boolean restIsConcrete = true;
228     for (int i = 1; i < adviceParamTypes.length; i++)
229       {
230         if (Wildcard.class.isAssignableFrom(adviceParamTypes[i]))
231           restIsConcrete = false;
232         else
233           restIsWildcard = false;
234       }
235
236     // and update the result
237
if (restIsWildcard && adviceParamTypes.length == 2 && adviceParamTypes[1].equals(wildcardClass))
238       optimization |= WILDCARD_2;
239     if (restIsConcrete)
240       optimization |= CONCRETE_2;
241
242     signatureCathegory = optimization;
243       }
244
245
246     protected boolean isAssignable(Class JavaDoc[] actualParameterType, Class JavaDoc formalParameterType)
247       {
248         if (Wildcard.class.isAssignableFrom(formalParameterType))
249       {
250         try
251           {
252         if (((Wildcard)formalParameterType.newInstance()).isAssignableFrom(actualParameterType))
253           return true;
254           }
255         catch (IllegalAccessException JavaDoc noConstructor)
256           {
257         throw new Error JavaDoc(noConstructor.toString());
258           }
259         catch (InstantiationException JavaDoc wrongConstructor)
260           {
261         throw new Error JavaDoc(wrongConstructor.toString());
262           }
263         return false;
264       }
265         else
266           return false;
267       }
268
269 }
270
271
272 //======================================================================
273
//
274
// $Log: SignaturePattern.java,v $
275
// Revision 1.2 2003/07/11 12:27:43 apopovic
276
// Bug fix for rare cases. Some classed loaded late may throw a 'NoClassDefError' when
277
// trying to retrieve the declared methods; The crosscut for such cases is now an empty listt
278
//
279
// Revision 1.1.1.1 2003/07/02 15:30:51 apopovic
280
// Imported from ETH Zurich
281
//
282
// Revision 1.2 2003/05/06 15:51:31 popovici
283
// Mozilla-ification
284
//
285
// Revision 1.1 2003/05/05 13:58:14 popovici
286
// renaming from runes to prose
287
//
288
// Revision 1.1 2003/04/17 12:49:23 popovici
289
// Refactoring of the crosscut package
290
// ExceptionCut renamed to ThrowCut
291
// McutSignature is now SignaturePattern
292
//
293
// Revision 1.2 2003/04/17 08:47:20 popovici
294
// Important functionality additions
295
// - Cflow specializers
296
// - Restructuring of the MethodCut, SetCut, ThrowCut, and GetCut (they are much smaller)
297
// - Transactional capabilities
298
// - Total refactoring of Specializer evaluation, which permits fine-grained distinction
299
// between static and dynamic specializers.
300
// - Functionality pulled up in abstract classes
301
// - Uniformization of advice methods patterns and names
302
//
303
// Revision 1.1 2003/03/05 15:26:41 popovici
304
// Bug fixes after the extraction of 'AdviceMethod' and 'AdviceExcecution' as top level classes:
305
// - a new Abstract class is superclassing 'UserDefinedAdvice' and 'DefaultAdvice'
306
//
307
Popular Tags