KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > codehaus > aspectwerkz > transform > inlining > weaver > AddInterfaceVisitor


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.inlining.weaver;
9
10 import java.util.Iterator JavaDoc;
11 import java.util.Set JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.List JavaDoc;
14
15 import org.objectweb.asm.*;
16 import org.codehaus.aspectwerkz.transform.Context;
17 import org.codehaus.aspectwerkz.transform.TransformationConstants;
18 import org.codehaus.aspectwerkz.transform.TransformationUtil;
19 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl;
20 import org.codehaus.aspectwerkz.definition.SystemDefinition;
21 import org.codehaus.aspectwerkz.definition.InterfaceIntroductionDefinition;
22 import org.codehaus.aspectwerkz.definition.MixinDefinition;
23 import org.codehaus.aspectwerkz.expression.ExpressionContext;
24 import org.codehaus.aspectwerkz.expression.PointcutType;
25 import org.codehaus.aspectwerkz.reflect.ClassInfo;
26 import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
27
28 /**
29  * Adds an interface to the target class.
30  *
31  * @author <a HREF="mailto:jboner@codehaus.org">Jonas Bonér </a>
32  * @author <a HREF="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
33  */

34 public class AddInterfaceVisitor extends ClassAdapter implements TransformationConstants {
35
36     private final static String JavaDoc ADVISABLE_MIXIN_IMPL_NAME = "org.codehaus.aspectwerkz.intercept.AdvisableImpl";
37
38     private final ContextImpl m_ctx;
39     private final ClassInfo m_classInfo;
40
41     /**
42      * Creates a new add interface class adapter.
43      *
44      * @param cv
45      * @param classInfo
46      * @param ctx
47      */

48     public AddInterfaceVisitor(final ClassVisitor cv,
49                                final ClassInfo classInfo,
50                                final Context ctx) {
51         super(cv);
52         m_classInfo = classInfo;
53         m_ctx = (ContextImpl) ctx;
54     }
55
56     /**
57      * Visits the class.
58      *
59      * @param access
60      * @param name
61      * @param superName
62      * @param interfaces
63      * @param sourceFile
64      */

65     public void visit(final int version,
66                       final int access,
67                       final String JavaDoc name,
68                       final String JavaDoc superName,
69                       final String JavaDoc[] interfaces,
70                       final String JavaDoc sourceFile) {
71         ExpressionContext ctx = new ExpressionContext(PointcutType.WITHIN, m_classInfo, m_classInfo);
72         if (classFilter(m_classInfo, ctx, m_ctx.getDefinitions())) {
73             super.visit(version, access, name, superName, interfaces, sourceFile);
74             return;
75         }
76
77         // javaclass names of interface to have
78
// use a Set to avoid doublons
79
final Set JavaDoc interfacesToAdd = new HashSet JavaDoc();
80
81         // already there interface javaclass names
82
for (int i = 0; i < interfaces.length; i++) {
83             interfacesToAdd.add(interfaces[i].replace('/', '.'));
84         }
85
86         // add new ones
87
final Set JavaDoc systemDefinitions = m_ctx.getDefinitions();
88         for (Iterator JavaDoc it = systemDefinitions.iterator(); it.hasNext();) {
89             SystemDefinition systemDefinition = (SystemDefinition) it.next();
90             final List JavaDoc interfaceIntroDefs = systemDefinition.getInterfaceIntroductionDefinitions(ctx);
91             for (Iterator JavaDoc it2 = interfaceIntroDefs.iterator(); it2.hasNext();) {
92                 final InterfaceIntroductionDefinition interfaceIntroDef = (InterfaceIntroductionDefinition) it2.next();
93                 interfacesToAdd.addAll(interfaceIntroDef.getInterfaceClassNames());
94             }
95             final List JavaDoc mixinDefinitions = systemDefinition.getMixinDefinitions(ctx);
96             for (Iterator JavaDoc it2 = mixinDefinitions.iterator(); it2.hasNext();) {
97                 final MixinDefinition mixinDef = (MixinDefinition) it2.next();
98                 if (ADVISABLE_MIXIN_IMPL_NAME.equals(mixinDef.getMixinImpl().getName())) {
99                     // mark it as made advisable
100
m_ctx.markMadeAdvisable();
101                 }
102                 final List JavaDoc interfaceList = mixinDef.getInterfaceClassNames();
103                 for (Iterator JavaDoc it3 = interfaceList.iterator(); it3.hasNext();) {
104                     interfacesToAdd.add(((String JavaDoc) it3.next()));
105                 }
106             }
107         }
108
109         if (ClassInfoHelper.hasMethodClash(interfacesToAdd, m_ctx.getLoader())) {
110             super.visit(version, access, name, superName, interfaces, sourceFile);
111             return;
112         }
113
114         int i = 0;
115         final String JavaDoc[] newInterfaceArray = new String JavaDoc[interfacesToAdd.size()];
116         for (Iterator JavaDoc it = interfacesToAdd.iterator(); it.hasNext();) {
117             newInterfaceArray[i++] = (String JavaDoc) it.next();
118         }
119
120         for (int j = 0; j < newInterfaceArray.length; j++) {
121             newInterfaceArray[j] = newInterfaceArray[j].replace('.', '/');
122
123         }
124         super.visit(version, access, name, superName, newInterfaceArray, sourceFile);
125         m_ctx.markAsAdvised();
126     }
127
128     /**
129      * Filters the classes to be transformed.
130      *
131      * @param classInfo the class to filter
132      * @param ctx the context
133      * @param definitions a set with the definitions
134      * @return boolean true if the method should be filtered away
135      */

136     public static boolean classFilter(final ClassInfo classInfo,
137                                       final ExpressionContext ctx,
138                                       final Set JavaDoc definitions) {
139         for (Iterator JavaDoc it = definitions.iterator(); it.hasNext();) {
140             SystemDefinition systemDef = (SystemDefinition) it.next();
141             if (classInfo.isInterface()) {
142                 return true;
143             }
144             String JavaDoc className = classInfo.getName().replace('/', '.');
145             if (systemDef.inExcludePackage(className)) {
146                 return true;
147             }
148             if (!systemDef.inIncludePackage(className)) {
149                 return true;
150             }
151             if (systemDef.hasMixin(ctx) || systemDef.hasIntroducedInterface(ctx)) {
152                 return false;
153             }
154         }
155         return true;
156     }
157 }
Popular Tags