1 /***************************************************************************************
2 * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. *
3 * http://aspectwerkz.codehaus.org *
4 * ---------------------------------------------------------------------------------- *
5 * The software in this package is published under the terms of the LGPL license *
6 * a copy of which has been included with this distribution in the license.txt file. *
7 **************************************************************************************/
8 package org.codehaus.aspectwerkz.transform.delegation;
9
10 import org.codehaus.aspectwerkz.MethodComparator;
11 import org.codehaus.aspectwerkz.annotation.instrumentation.AttributeEnhancer;
12 import org.codehaus.aspectwerkz.definition.SystemDefinition;
13 import org.codehaus.aspectwerkz.transform.Context;
14 import org.codehaus.aspectwerkz.transform.TransformationUtil;
15 import org.codehaus.aspectwerkz.transform.TransformationConstants;
16 import org.codehaus.aspectwerkz.transform.TransformationConstants;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.DataOutputStream;
20 import java.io.IOException;
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.Comparator;
27 import java.util.Iterator;
28 import java.util.List;
29
30 import javassist.CannotCompileException;
31 import javassist.ClassPool;
32 import javassist.CtClass;
33 import javassist.CtConstructor;
34 import javassist.CtField;
35 import javassist.CtMethod;
36 import javassist.CtNewMethod;
37 import javassist.Modifier;
38 import javassist.NotFoundException;
39 import javassist.CtBehavior;
40 import javassist.bytecode.AttributeInfo;
41 import javassist.bytecode.ClassFile;
42 import javassist.bytecode.Descriptor;
43 import javassist.bytecode.AnnotationsAttribute;
44
45 /***
46 * Helper class with utility methods for Javassist.
47 *
48 * @author <a href="mailto:alex@gnilux.com">Alexandre Vasseur </a>
49 * @author <a href="mailto:jboner@codehaus.org">Jonas Bonér </a>
50 */
51 public class JavassistHelper {
52 /***
53 * Helper method for bogus CtMethod.make in Javassist for static methods
54 *
55 * @param returnType
56 * @param name
57 * @param parameters
58 * @param exceptions
59 * @param body
60 * @param declaring
61 * @return new method
62 * @throws CannotCompileException
63 */
64 public static CtMethod makeStatic(
65 final CtClass returnType,
66 final String name,
67 final CtClass[] parameters,
68 final CtClass[] exceptions,
69 final String body,
70 final CtClass declaring) throws CannotCompileException {
71 try {
72 CtMethod cm = new CtMethod(returnType, name, parameters, declaring);
73 cm.setModifiers(cm.getModifiers() | Modifier.STATIC);
74 cm.setExceptionTypes(exceptions);
75 cm.setBody(body);
76 return cm;
77 } catch (NotFoundException e) {
78 throw new CannotCompileException(e);
79 }
80 }
81
82 /***
83 * Gets the default value for primitive types
84 *
85 * @param type
86 * @return
87 */
88 public static String getDefaultPrimitiveValue(CtClass type) {
89 if (type == CtClass.booleanType) {
90 return "false";
91 } else if (type == CtClass.intType) {
92 return "0";
93 } else if (type == CtClass.longType) {
94 return "0L";
95 } else if (type == CtClass.floatType) {
96 return "0.0f";
97 } else if (type == CtClass.shortType) {
98 return "(short)0";
99 } else if (type == CtClass.byteType) {
100 return "(byte)0";
101 } else if (type == CtClass.charType) {
102 return "'//u0000'";
103 } else if (type == CtClass.doubleType) {
104 return "(double)0";
105 } else {
106 return "null";
107 }
108 }
109
110 /***
111 * Checks if the given Class as already a method methodName Does not take into account the signature
112 *
113 * @param klass
114 * @param methodName
115 * @return true if klass has methodName
116 */
117 public static boolean hasMethod(CtClass klass, String methodName) {
118 try {
119 klass.getDeclaredMethod(methodName);
120 return true;
121 } catch (NotFoundException e) {
122 return false;
123 }
124 }
125
126 /***
127 * Checks if the given Class as already a ctor with given signature
128 *
129 * @param klass
130 * @param args
131 * @return true if klass has ctor
132 */
133 public static boolean hasConstructor(CtClass klass, CtClass[] args) {
134 try {
135 klass.getDeclaredConstructor(args);
136 return true;
137 } catch (NotFoundException e) {
138 return false;
139 }
140 }
141
142 /***
143 * Checks if the given Class as already a method methodName Does not take into account the signature
144 *
145 * @param klass
146 * @param fieldName
147 * @return true if klass has methodName
148 */
149 public static boolean hasField(CtClass klass, String fieldName) {
150 try {
151 klass.getDeclaredField(fieldName);
152 return true;
153 } catch (NotFoundException e) {
154 return false;
155 }
156 }
157
158 /***
159 * Checks if the given Class as already a method methodName.
160 *
161 * @param klass
162 * @param methodName
163 * @return true if klass has methodName
164 */
165 public static boolean hasMethod(CtClass klass, String methodName, CtClass[] args) {
166 try {
167 klass.getDeclaredMethod(methodName, args);
168 return true;
169 } catch (NotFoundException e) {
170 return false;
171 }
172 }
173
174 /***
175 * Swapp bodies of the two given methods of the same declaring class
176 *
177 * @param methodA
178 * @param methodB
179 * @TODO: add support for annotations
180 */
181 public static void swapBodies(CtMethod methodA, CtMethod methodB) {
182 String nameA = methodA.getName();
183 int modifiersA = methodA.getModifiers();
184 methodA.setName(methodB.getName());
185 methodA.setModifiers(methodB.getModifiers());
186 methodB.setName(nameA);
187 methodB.setModifiers(modifiersA);
188 }
189
190 /***
191 * Converts a Javassist type signature to a reflect type signature. <p/>Since <b>sucky </b> Javassist does not use
192 * the standard.
193 *
194 * @param typeName
195 * @return @TODO does not support multi dimensional arrays, needs to be fixed
196 */
197 public static String convertJavassistTypeSignatureToReflectTypeSignature(String typeName) {
198 int index = typeName.indexOf("[]");
199 if (index >= 0) {
200 typeName = typeName.substring(0, index);
201 if (typeName.equals("short")) {
202 typeName = "[S";
203 } else if (typeName.equals("int")) {
204 typeName = "[I";
205 } else if (typeName.equals("long")) {
206 typeName = "[J";
207 } else if (typeName.equals("float")) {
208 typeName = "[F";
209 } else if (typeName.equals("double")) {
210 typeName = "[D";
211 } else if (typeName.equals("char")) {
212 typeName = "[C";
213 } else if (typeName.equals("byte")) {
214 typeName = "[B";
215 } else if (typeName.equals("boolean")) {
216 typeName = "[Z";
217 } else {
218 typeName = "[L" + typeName + ';';
219 }
220 }
221 return typeName;
222 }
223
224 /***
225 * Checks if a method is marked as an empty wrapper (runtime weaving)
226 *
227 * @param method
228 * @return true if empty wrapper
229 */
230 public static boolean isAnnotatedEmpty(CtMethod method) {
231 byte[] emptyBytes = method.getAttribute(TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE);
232 return ((emptyBytes != null) && (emptyBytes[0] == TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE_VALUE_EMPTY));
233 }
234
235 /***
236 * Checks if a method is marked as a non empty wrapper (runtime unweaving)
237 *
238 * @param method
239 * @return true if non empty wrapper
240 */
241 public static boolean isAnnotatedNotEmpty(CtMethod method) {
242 byte[] emptyBytes = method.getAttribute(TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE);
243 return ((emptyBytes == null) || (emptyBytes[0] == TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE_VALUE_NOTEMPTY));
244 }
245
246 /***
247 * Sets a method as beeing an empty wrapper
248 *
249 * @param method
250 */
251 public static void setAnnotatedEmpty(CtMethod method) {
252 method.setAttribute(TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE, new byte[] {
253 TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE_VALUE_EMPTY
254 });
255 }
256
257 /***
258 * Sets a method as beeing a non empty wrapper
259 *
260 * @param method
261 */
262 public static void setAnnotatedNotEmpty(CtMethod method) {
263 method.setAttribute(TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE, new byte[] {
264 TransformationConstants.EMPTY_WRAPPER_ATTRIBUTE_VALUE_NOTEMPTY
265 });
266 }
267
268 /***
269 * Creates an empty wrapper method to allow HotSwap without schema change <p/>TODO refactor PrepareTransformer
270 * CAUTION: does not check the wrapped method already exists while PrepareTransformer version does
271 *
272 * @param ctClass the ClassGen
273 * @param originalMethod the current method
274 * @param methodSequence the method hash
275 * @return the wrapper method
276 */
277 public static CtMethod createEmptyWrapperMethod(
278 final CtClass ctClass,
279 final CtMethod originalMethod,
280 final int methodSequence) throws NotFoundException, CannotCompileException {
281 String wrapperMethodName = TransformationUtil.getPrefixedOriginalMethodName(
282 originalMethod.getName(),
283 methodSequence,
284 ctClass.getName().replace('/', '.'));
285
286
287 int accessFlags = originalMethod.getModifiers();
288 if ((accessFlags & Modifier.PROTECTED) == 0) {
289
290 accessFlags |= Modifier.PROTECTED;
291 }
292 if ((accessFlags & Modifier.PRIVATE) != 0) {
293
294 accessFlags &= ~Modifier.PRIVATE;
295 }
296 if ((accessFlags & Modifier.PUBLIC) != 0) {
297
298 accessFlags &= ~Modifier.PUBLIC;
299 }
300
301
302 StringBuffer body = new StringBuffer();
303 if (originalMethod.getReturnType() == CtClass.voidType) {
304
305
306 body.append("{}");
307 } else if (!originalMethod.getReturnType().isPrimitive()) {
308 body.append("{ return null;}");
309 } else {
310 body.append("{ return ");
311 body.append(JavassistHelper.getDefaultPrimitiveValue(originalMethod.getReturnType()));
312 body.append("; }");
313 }
314 CtMethod method = null;
315 if (Modifier.isStatic(originalMethod.getModifiers())) {
316 method = JavassistHelper.makeStatic(originalMethod.getReturnType(), wrapperMethodName, originalMethod
317 .getParameterTypes(), originalMethod.getExceptionTypes(), body.toString(), ctClass);
318 } else {
319 method = CtNewMethod.make(originalMethod.getReturnType(), wrapperMethodName, originalMethod
320 .getParameterTypes(), originalMethod.getExceptionTypes(), body.toString(), ctClass);
321 method.setModifiers(accessFlags);
322 }
323 JavassistHelper.copyCustomAttributes(method, originalMethod);
324
325
326
327 JavassistHelper.setAnnotatedEmpty(method);
328 return method;
329 }
330
331 /***
332 * Copy pasted from Javassist since it is a private method
333 *
334 * @param clazz
335 * @return @throws CannotCompileException
336 */
337 public static long calculateSerialVerUid(CtClass clazz) throws CannotCompileException {
338 try {
339 ByteArrayOutputStream bout = new ByteArrayOutputStream();
340 DataOutputStream out = new DataOutputStream(bout);
341 ClassFile classFile = clazz.getClassFile();
342
343
344 String javaName = javaName(clazz);
345 out.writeUTF(javaName);
346
347
348 out.writeInt(clazz.getModifiers()
349 & (Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT));
350
351
352 String[] interfaces = classFile.getInterfaces();
353 for (int i = 0; i < interfaces.length; i++) {
354 interfaces[i] = javaName(interfaces[i]);
355 }
356 Arrays.sort(interfaces);
357 for (int i = 0; i < interfaces.length; i++) {
358 out.writeUTF(interfaces[i]);
359 }
360
361
362 CtField[] fields = clazz.getDeclaredFields();
363 Arrays.sort(fields, new Comparator() {
364 public int compare(Object o1, Object o2) {
365 CtField field1 = (CtField) o1;
366 CtField field2 = (CtField) o2;
367 return field1.getName().compareTo(field2.getName());
368 }
369 });
370 for (int i = 0; i < fields.length; i++) {
371 CtField field = (CtField) fields[i];
372 int mods = field.getModifiers();
373 if (((mods & Modifier.PRIVATE) == 0) || ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) {
374 out.writeUTF(field.getName());
375 out.writeInt(mods & filterFieldModifiers());
376 out.writeUTF(field.getFieldInfo2().getDescriptor());
377 }
378 }
379
380
381 if (classFile.getStaticInitializer() != null) {
382 out.writeUTF("<clinit>");
383 out.writeInt(Modifier.STATIC);
384 out.writeUTF("()V");
385 }
386
387
388 CtConstructor[] constructors = clazz.getDeclaredConstructors();
389 Arrays.sort(constructors, new Comparator() {
390 public int compare(Object o1, Object o2) {
391 CtConstructor c1 = (CtConstructor) o1;
392 CtConstructor c2 = (CtConstructor) o2;
393 return c1.getMethodInfo2().getDescriptor().compareTo(c2.getMethodInfo2().getDescriptor());
394 }
395 });
396 for (int i = 0; i < constructors.length; i++) {
397 CtConstructor constructor = constructors[i];
398 int mods = constructor.getModifiers();
399 if ((mods & Modifier.PRIVATE) == 0) {
400 out.writeUTF("<init>");
401 out.writeInt(mods & filterConstructorModifiers());
402 out.writeUTF(constructor.getMethodInfo2().getDescriptor().replace('/', '.'));
403 }
404 }
405
406
407 CtMethod[] methods = clazz.getDeclaredMethods();
408 Arrays.sort(methods, new Comparator() {
409 public int compare(Object o1, Object o2) {
410 CtMethod m1 = (CtMethod) o1;
411 CtMethod m2 = (CtMethod) o2;
412 int value = m1.getName().compareTo(m2.getName());
413 if (value == 0) {
414 value = m1.getMethodInfo2().getDescriptor().compareTo(m2.getMethodInfo2().getDescriptor());
415 }
416 return value;
417 }
418 });
419 for (int i = 0; i < methods.length; i++) {
420 CtMethod method = methods[i];
421 int mods = method.getModifiers();
422 if ((mods & Modifier.PRIVATE) == 0) {
423 out.writeUTF(method.getName());
424 out.writeInt(mods & filterMethodModifiers());
425 out.writeUTF(method.getMethodInfo2().getDescriptor().replace('/', '.'));
426 }
427 }
428
429
430 out.flush();
431 MessageDigest digest = MessageDigest.getInstance("SHA");
432 byte[] digested = digest.digest(bout.toByteArray());
433 long hash = 0;
434 for (int i = Math.min(digested.length, 8) - 1; i >= 0; i--) {
435 hash = (hash << 8) | (digested[i] & 0xFF);
436 }
437 return hash;
438 } catch (IOException e) {
439 throw new CannotCompileException(e);
440 } catch (NoSuchAlgorithmException e) {
441 throw new CannotCompileException(e);
442 }
443 }
444
445 private static int filterFieldModifiers(){
446 return (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED
447 | Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | Modifier.VOLATILE);
448 }
449
450 private static int filterConstructorModifiers(){
451 return (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
452 }
453
454 private static int filterMethodModifiers(){
455 return (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED
456 | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED
457 | Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT);
458 }
459
460 private static String javaName(CtClass clazz) {
461 return Descriptor.toJavaName(Descriptor.toJvmName(clazz));
462 }
463
464 private static String javaName(String name) {
465 return Descriptor.toJavaName(Descriptor.toJvmName(name));
466 }
467
468 public static void setSerialVersionUID(CtClass clazz, long serialVerUid) throws CannotCompileException {
469
470 CtField field = new CtField(CtClass.longType, "serialVersionUID", clazz);
471 field.setModifiers(Modifier.PRIVATE | Modifier.STATIC | Modifier.FINAL);
472 clazz.addField(field, serialVerUid + "L");
473 }
474
475 /***
476 * Does the class implement Serializable?
477 */
478 private static boolean isSerializable(CtClass clazz) throws NotFoundException {
479 ClassPool pool = clazz.getClassPool();
480 return clazz.subtypeOf(pool.get("java.io.Serializable"));
481 }
482
483 public static boolean isSerialVerUidNeeded(CtClass clazz) throws NotFoundException {
484
485 try {
486 clazz.getDeclaredField("serialVersionUID");
487 return false;
488 } catch (NotFoundException e) {
489 }
490
491
492 if (!isSerializable(clazz)) {
493 return false;
494 }
495 return true;
496 }
497
498 /***
499 * Adds a new <code>AspectManager</code> field to the advised class.
500 *
501 * @param ctClass
502 * @param definition
503 */
504 public static void addAspectManagerField(
505 final CtClass ctClass,
506 final SystemDefinition definition,
507 final Context context) throws NotFoundException, CannotCompileException {
508 if (!hasField(ctClass, TransformationConstants.ASPECT_MANAGER_FIELD)) {
509 CtField field = new CtField(
510 ctClass.getClassPool().get(TransformationConstants.ASPECT_MANAGER_CLASS),
511 TransformationConstants.ASPECT_MANAGER_FIELD,
512 ctClass);
513 field.setModifiers(Modifier.STATIC | Modifier.PRIVATE | Modifier.FINAL);
514 StringBuffer body = new StringBuffer();
515 body.append(TransformationConstants.SYSTEM_LOADER_CLASS);
516 body.append("#getSystem(");
517 body.append(TransformationConstants.STATIC_CLASS_FIELD);
518 body.append('.');
519 body.append("getClassLoader())");
520 body.append('.');
521 body.append(TransformationConstants.GET_ASPECT_MANAGER_METHOD);
522 body.append("(\"");
523 body.append(definition.getUuid());
524 body.append("\");");
525
526
527
528
529
530
531 ctClass.addField(field, body.toString());
532 context.markAsAdvised();
533 }
534 }
535
536 /***
537 * Creates a new static class field.
538 *
539 * @param ctClass the class
540 */
541 public static void addStaticClassField(final CtClass ctClass, final Context context) throws NotFoundException,
542 CannotCompileException {
543 if (!hasField(ctClass, TransformationConstants.STATIC_CLASS_FIELD)) {
544 CtField field = new CtField(
545 ctClass.getClassPool().get("java.lang.Class"),
546 TransformationConstants.STATIC_CLASS_FIELD,
547 ctClass);
548 field.setModifiers(Modifier.STATIC | Modifier.PRIVATE | Modifier.FINAL);
549 ctClass.addField(field, "java.lang.Class#forName(\"" + ctClass.getName().replace('/', '.') + "\")");
550 context.markAsAdvised();
551 }
552 }
553
554 /***
555 * Adds a new <code>JoinPointManager</code> field to the advised class.
556 *
557 * @param ctClass
558 * @param definition
559 */
560 public static void addJoinPointManagerField(
561 final CtClass ctClass,
562 final SystemDefinition definition,
563 final Context context) throws NotFoundException, CannotCompileException {
564 if (!hasField(ctClass, TransformationConstants.JOIN_POINT_MANAGER_FIELD)) {
565 CtField field = new CtField(
566 ctClass.getClassPool().get(TransformationConstants.JOIN_POINT_MANAGER_CLASS),
567 TransformationConstants.JOIN_POINT_MANAGER_FIELD,
568 ctClass);
569 field.setModifiers(Modifier.STATIC | Modifier.PRIVATE);
570 StringBuffer body = new StringBuffer();
571 body.append(TransformationConstants.JOIN_POINT_MANAGER_CLASS);
572 body.append('#');
573 body.append(TransformationConstants.GET_JOIN_POINT_MANAGER);
574 body.append('(');
575 body.append(TransformationConstants.STATIC_CLASS_FIELD);
576 body.append(", \"");
577 body.append(definition.getUuid());
578 body.append("\")");
579 ctClass.addField(field, body.toString());
580 context.markAsAdvised();
581 }
582 }
583
584 /***
585 * Copies the custom attributes from one class to another.
586 *
587 * @param copyTo
588 * @param copyFrom
589 */
590 public static void copyCustomAttributes(final CtBehavior copyTo, final CtBehavior copyFrom) {
591 List attributes = copyFrom.getMethodInfo().getAttributes();
592 for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
593 AttributeInfo attributeInfo = (AttributeInfo) iterator.next();
594
595
596 if (attributeInfo.getName().startsWith("RuntimeInvisibleAnnotations")
597 || attributeInfo.getName().startsWith("RuntimeVisibleAnnotations")) {
598 copyTo.setAttribute(attributeInfo.getName(), ((AnnotationsAttribute)attributeInfo).get());
599 }
600 }
601 }
602
603 /***
604 * Calculate the hash for a javassist field.
605 *
606 * @param field the field
607 * @return the hash
608 */
609 public static int calculateHash(final CtField field) throws NotFoundException {
610 int hash = 17;
611 hash = (37 * hash) + field.getName().hashCode();
612 String name = convertJavassistTypeSignatureToReflectTypeSignature(field.getType().getName().replace('/', '.'));
613 hash = (37 * hash) + name.hashCode();
614 return hash;
615 }
616
617 /***
618 * Calculate the hash for a javassist constructor.
619 *
620 * @param constructor the constructor
621 * @return the hash
622 */
623 public static int calculateHash(final CtConstructor constructor) throws NotFoundException {
624 int hash = 17;
625 hash = (37 * hash) + TransformationConstants.INIT_METHOD_NAME.hashCode();
626 for (int i = 0; i < constructor.getParameterTypes().length; i++) {
627 CtClass type = constructor.getParameterTypes()[i];
628 String name = convertJavassistTypeSignatureToReflectTypeSignature(type.getName().replace('/', '.'));
629 hash = (37 * hash) + name.hashCode();
630 }
631 return hash;
632 }
633
634 /***
635 * Calculate the hash for a javassist method.
636 *
637 * @param method the method
638 * @return the hash
639 */
640 public static int calculateHash(final CtMethod method) throws NotFoundException {
641 int hash = 17;
642 hash = (37 * hash) + method.getName().hashCode();
643 for (int i = 0; i < method.getParameterTypes().length; i++) {
644 CtClass type = method.getParameterTypes()[i];
645 String name = convertJavassistTypeSignatureToReflectTypeSignature(type.getName().replace('/', '.'));
646 hash = (37 * hash) + name.hashCode();
647 }
648 return hash;
649 }
650
651 /***
652 * Calculate the hash for a class.
653 *
654 * @param ctClass the class
655 * @return the hash
656 */
657 public static int calculateHash(final CtClass ctClass) throws NotFoundException {
658 return ctClass.getName().hashCode();
659 }
660
661 /***
662 * Creates a sorted method list of all the public methods in the class and super classes.
663 *
664 * @TODO NOT IN USE - REMOVE
665 *
666 * @param klass the class with the methods
667 * @return the sorted method list
668 */
669 public static List createSortedMethodList(final CtClass klass) {
670 if (klass == null) {
671 throw new IllegalArgumentException("class to sort method on can not be null");
672 }
673
674
675 CtMethod[] methods = klass.getDeclaredMethods();
676 List methodList = new ArrayList(methods.length);
677 for (int i = 0; i < methods.length; i++) {
678 CtMethod method = methods[i];
679 if (!method.getName().equals("equals")
680 && !method.getName().equals("hashCode")
681 && !method.getName().equals("getClass")
682 && !method.getName().equals("toString")
683 && !method.getName().equals("wait")
684 && !method.getName().equals("notify")
685 && !method.getName().equals("notifyAll")
686 && !method.getName().startsWith(TransformationConstants.CLASS_LOOKUP_METHOD)
687 && !method.getName().startsWith(TransformationConstants.ORIGINAL_METHOD_PREFIX)
688 && !method.getName().startsWith(TransformationConstants.ASPECTWERKZ_PREFIX)) {
689 methodList.add(method);
690 }
691 }
692 Collections.sort(methodList, MethodComparator.getInstance(MethodComparator.NORMAL_METHOD));
693 return methodList;
694 }
695
696 /***
697 * Returrns the join point index for the class.
698 *
699 * @param klass
700 * @return the index
701 */
702 public static int getJoinPointIndex(final CtClass klass) {
703 byte[] attribute = klass.getAttribute(TransformationConstants.JOIN_POINT_INDEX_ATTRIBUTE);
704 if (attribute == null) {
705 klass.setAttribute(TransformationConstants.JOIN_POINT_INDEX_ATTRIBUTE, new byte[] {
706 new Integer(0).byteValue()
707 });
708 return 0;
709 }
710 return new Integer(attribute[0]).intValue();
711 }
712
713 /***
714 * Sets the join point index for the class.
715 *
716 * @param klass
717 * @param index
718 */
719 public static void setJoinPointIndex(final CtClass klass, final int index) {
720 klass.setAttribute(TransformationConstants.JOIN_POINT_INDEX_ATTRIBUTE, new byte[] {
721 new Integer(index).byteValue()
722 });
723 }
724 }