001: /**************************************************************************************
002: * Copyright (c) Jonas BonŽr, Alexandre Vasseur. All rights reserved. *
003: * http://aspectwerkz.codehaus.org *
004: * ---------------------------------------------------------------------------------- *
005: * The software in this package is published under the terms of the LGPL license *
006: * a copy of which has been included with this distribution in the license.txt file. *
007: **************************************************************************************/package org.codehaus.aspectwerkz.transform.inlining.weaver;
008:
009: import java.util.Iterator;
010: import java.util.Set;
011: import java.util.HashSet;
012: import java.util.List;
013:
014: import org.objectweb.asm.*;
015: import org.codehaus.aspectwerkz.transform.Context;
016: import org.codehaus.aspectwerkz.transform.TransformationConstants;
017: import org.codehaus.aspectwerkz.transform.TransformationUtil;
018: import org.codehaus.aspectwerkz.transform.inlining.ContextImpl;
019: import org.codehaus.aspectwerkz.definition.SystemDefinition;
020: import org.codehaus.aspectwerkz.definition.InterfaceIntroductionDefinition;
021: import org.codehaus.aspectwerkz.definition.MixinDefinition;
022: import org.codehaus.aspectwerkz.expression.ExpressionContext;
023: import org.codehaus.aspectwerkz.expression.PointcutType;
024: import org.codehaus.aspectwerkz.reflect.ClassInfo;
025: import org.codehaus.aspectwerkz.reflect.ClassInfoHelper;
026:
027: /**
028: * Adds an interface to the target class.
029: *
030: * @author <a href="mailto:jboner@codehaus.org">Jonas BonŽr </a>
031: * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
032: */
033: public class AddInterfaceVisitor extends ClassAdapter implements
034: TransformationConstants {
035:
036: private final static String ADVISABLE_MIXIN_IMPL_NAME = "org.codehaus.aspectwerkz.intercept.AdvisableImpl";
037:
038: private final ContextImpl m_ctx;
039: private final ClassInfo m_classInfo;
040:
041: /**
042: * Creates a new add interface class adapter.
043: *
044: * @param cv
045: * @param classInfo
046: * @param ctx
047: */
048: public AddInterfaceVisitor(final ClassVisitor cv,
049: final ClassInfo classInfo, final Context ctx) {
050: super (cv);
051: m_classInfo = classInfo;
052: m_ctx = (ContextImpl) ctx;
053: }
054:
055: /**
056: * Visits the class.
057: *
058: * @param access
059: * @param name
060: * @param superName
061: * @param interfaces
062: * @param sourceFile
063: */
064: public void visit(final int version, final int access,
065: final String name, final String super Name,
066: final String[] interfaces, final String sourceFile) {
067: ExpressionContext ctx = new ExpressionContext(
068: PointcutType.WITHIN, m_classInfo, m_classInfo);
069: if (classFilter(m_classInfo, ctx, m_ctx.getDefinitions())) {
070: super .visit(version, access, name, super Name, interfaces,
071: sourceFile);
072: return;
073: }
074:
075: // javaclass names of interface to have
076: // use a Set to avoid doublons
077: final Set interfacesToAdd = new HashSet();
078:
079: // already there interface javaclass names
080: for (int i = 0; i < interfaces.length; i++) {
081: interfacesToAdd.add(interfaces[i].replace('/', '.'));
082: }
083:
084: // add new ones
085: final Set systemDefinitions = m_ctx.getDefinitions();
086: for (Iterator it = systemDefinitions.iterator(); it.hasNext();) {
087: SystemDefinition systemDefinition = (SystemDefinition) it
088: .next();
089: final List interfaceIntroDefs = systemDefinition
090: .getInterfaceIntroductionDefinitions(ctx);
091: for (Iterator it2 = interfaceIntroDefs.iterator(); it2
092: .hasNext();) {
093: final InterfaceIntroductionDefinition interfaceIntroDef = (InterfaceIntroductionDefinition) it2
094: .next();
095: interfacesToAdd.addAll(interfaceIntroDef
096: .getInterfaceClassNames());
097: }
098: final List mixinDefinitions = systemDefinition
099: .getMixinDefinitions(ctx);
100: for (Iterator it2 = mixinDefinitions.iterator(); it2
101: .hasNext();) {
102: final MixinDefinition mixinDef = (MixinDefinition) it2
103: .next();
104: if (ADVISABLE_MIXIN_IMPL_NAME.equals(mixinDef
105: .getMixinImpl().getName())) {
106: // mark it as made advisable
107: m_ctx.markMadeAdvisable();
108: }
109: final List interfaceList = mixinDef
110: .getInterfaceClassNames();
111: for (Iterator it3 = interfaceList.iterator(); it3
112: .hasNext();) {
113: interfacesToAdd.add(((String) it3.next()));
114: }
115: }
116: }
117:
118: if (ClassInfoHelper.hasMethodClash(interfacesToAdd, m_ctx
119: .getLoader())) {
120: super .visit(version, access, name, super Name, interfaces,
121: sourceFile);
122: return;
123: }
124:
125: int i = 0;
126: final String[] newInterfaceArray = new String[interfacesToAdd
127: .size()];
128: for (Iterator it = interfacesToAdd.iterator(); it.hasNext();) {
129: newInterfaceArray[i++] = (String) it.next();
130: }
131:
132: for (int j = 0; j < newInterfaceArray.length; j++) {
133: newInterfaceArray[j] = newInterfaceArray[j].replace('.',
134: '/');
135:
136: }
137: super .visit(version, access, name, super Name,
138: newInterfaceArray, sourceFile);
139: m_ctx.markAsAdvised();
140: }
141:
142: /**
143: * Filters the classes to be transformed.
144: *
145: * @param classInfo the class to filter
146: * @param ctx the context
147: * @param definitions a set with the definitions
148: * @return boolean true if the method should be filtered away
149: */
150: public static boolean classFilter(final ClassInfo classInfo,
151: final ExpressionContext ctx, final Set definitions) {
152: for (Iterator it = definitions.iterator(); it.hasNext();) {
153: SystemDefinition systemDef = (SystemDefinition) it.next();
154: if (classInfo.isInterface()) {
155: return true;
156: }
157: String className = classInfo.getName().replace('/', '.');
158: if (systemDef.inExcludePackage(className)) {
159: return true;
160: }
161: if (!systemDef.inIncludePackage(className)) {
162: return true;
163: }
164: if (systemDef.hasMixin(ctx)
165: || systemDef.hasIntroducedInterface(ctx)) {
166: return false;
167: }
168: }
169: return true;
170: }
171: }
|