* which accompanies this distribution and is available at | * which accompanies this distribution and is available at | ||||
* http://eclipse.org/legal/epl-v10.html | * http://eclipse.org/legal/epl-v10.html | ||||
* | * | ||||
* Contributors: | |||||
* Contributors: | |||||
* Alexandre Vasseur initial implementation | * Alexandre Vasseur initial implementation | ||||
* ******************************************************************/ | * ******************************************************************/ | ||||
* Type munger for annotation style ITD declare parents. with an interface AND an implementation. Given the aspect that has a field | * Type munger for annotation style ITD declare parents. with an interface AND an implementation. Given the aspect that has a field | ||||
* public static Interface fieldI = ... // impl. we will weave in the Interface' methods and delegate to the aspect public static | * public static Interface fieldI = ... // impl. we will weave in the Interface' methods and delegate to the aspect public static | ||||
* field fieldI | * field fieldI | ||||
* | |||||
* | |||||
* Note: this munger DOES NOT handles the interface addition to the target classes - a regular Parent kinded munger must be added in | * Note: this munger DOES NOT handles the interface addition to the target classes - a regular Parent kinded munger must be added in | ||||
* coordination. | * coordination. | ||||
*/ | */ | ||||
/** | /** | ||||
* Construct a new type munger for @AspectJ ITD | * Construct a new type munger for @AspectJ ITD | ||||
* | |||||
* | |||||
* @param signature | * @param signature | ||||
* @param aspect | * @param aspect | ||||
* @param implClassName | * @param implClassName | ||||
kind.write(s); | kind.write(s); | ||||
signature.write(s); | signature.write(s); | ||||
aspect.write(s); | aspect.write(s); | ||||
s.writeUTF(implClassName); | |||||
s.writeUTF(implClassName==null?"":implClassName); | |||||
typePattern.write(s); | typePattern.write(s); | ||||
fieldType.write(s); | fieldType.write(s); | ||||
s.writeUTF(factoryMethodName); | s.writeUTF(factoryMethodName); | ||||
ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); | ResolvedMemberImpl signature = ResolvedMemberImpl.readResolvedMember(s, context); | ||||
UnresolvedType aspect = UnresolvedType.read(s); | UnresolvedType aspect = UnresolvedType.read(s); | ||||
String implClassName = s.readUTF(); | String implClassName = s.readUTF(); | ||||
if (implClassName.equals("")) { | |||||
implClassName = null; | |||||
} | |||||
TypePattern tp = TypePattern.read(s, context); | TypePattern tp = TypePattern.read(s, context); | ||||
MethodDelegateTypeMunger typeMunger = new MethodDelegateTypeMunger(signature, aspect, implClassName, tp); | MethodDelegateTypeMunger typeMunger = new MethodDelegateTypeMunger(signature, aspect, implClassName, tp); | ||||
UnresolvedType fieldType = null; | UnresolvedType fieldType = null; | ||||
/** | /** | ||||
* Match based on given type pattern, only classes can be matched | * Match based on given type pattern, only classes can be matched | ||||
* | |||||
* | |||||
* @param matchType | * @param matchType | ||||
* @param aspectType | * @param aspectType | ||||
* @return true if match | * @return true if match | ||||
/** | /** | ||||
* Needed for reweavable | * Needed for reweavable | ||||
* | |||||
* | |||||
* @return true | * @return true | ||||
*/ | */ | ||||
public boolean changesPublicSignature() { | public boolean changesPublicSignature() { | ||||
/** | /** | ||||
* Construct a new type munger for @AspectJ ITD | * Construct a new type munger for @AspectJ ITD | ||||
* | |||||
* | |||||
* @param field | * @param field | ||||
* @param aspect | * @param aspect | ||||
* @param typePattern | * @param typePattern | ||||
/** | /** | ||||
* Match based on given type pattern, only classes can be matched | * Match based on given type pattern, only classes can be matched | ||||
* | |||||
* | |||||
* @param matchType | * @param matchType | ||||
* @param aspectType | * @param aspectType | ||||
* @return true if match | * @return true if match |
/* ******************************************************************* | /* ******************************************************************* | ||||
* Copyright (c) 2005 IBM Corporation | * Copyright (c) 2005 IBM Corporation | ||||
* All rights reserved. | |||||
* This program and the accompanying materials are made available | |||||
* under the terms of the Eclipse Public License v1.0 | |||||
* which accompanies this distribution and is available at | |||||
* http://www.eclipse.org/legal/epl-v10.html | |||||
* | |||||
* Contributors: | |||||
* Adrian Colyer, | |||||
* All rights reserved. | |||||
* This program and the accompanying materials are made available | |||||
* under the terms of the Eclipse Public License v1.0 | |||||
* which accompanies this distribution and is available at | |||||
* http://www.eclipse.org/legal/epl-v10.html | |||||
* | |||||
* Contributors: | |||||
* Adrian Colyer, | |||||
* ******************************************************************/ | * ******************************************************************/ | ||||
package org.aspectj.testing; | package org.aspectj.testing; | ||||
import java.util.ArrayList; | |||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.ArrayList; | |||||
import java.util.StringTokenizer; | import java.util.StringTokenizer; | ||||
import org.aspectj.tools.ajc.AjcTestCase; | import org.aspectj.tools.ajc.AjcTestCase; | ||||
import org.aspectj.util.LangUtil; | import org.aspectj.util.LangUtil; | ||||
public class OutputSpec { | public class OutputSpec { | ||||
private List<String> expectedOutputLines = new ArrayList<String>(); | private List<String> expectedOutputLines = new ArrayList<String>(); | ||||
public void addLine(OutputLine line) { | public void addLine(OutputLine line) { | ||||
expectedOutputLines.add(line.getText()); | expectedOutputLines.add(line.getText()); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* For a test output line that has specified a vm version, check if it matches the vm we are running on. | * For a test output line that has specified a vm version, check if it matches the vm we are running on. | ||||
* vm might be "1.2,1.3,1.4,1.5" or simply "9" or it may be a version with a '+' suffix indicating that | * vm might be "1.2,1.3,1.4,1.5" or simply "9" or it may be a version with a '+' suffix indicating that | ||||
public void matchAgainst(String output) { | public void matchAgainst(String output) { | ||||
matchAgainst(output, "yes"); | matchAgainst(output, "yes"); | ||||
} | } | ||||
public void matchAgainst(String output, String ordered) { | public void matchAgainst(String output, String ordered) { | ||||
if (ordered != null && ordered.equals("no")) { | if (ordered != null && ordered.equals("no")) { | ||||
unorderedMatchAgainst(output); | unorderedMatchAgainst(output); | ||||
createFailureMessage(output, lineNo, strTok.countTokens()); | createFailureMessage(output, lineNo, strTok.countTokens()); | ||||
} | } | ||||
} | } | ||||
public void unorderedMatchAgainst(String output) { | public void unorderedMatchAgainst(String output) { | ||||
List<String> outputFound = getOutputFound(output); | List<String> outputFound = getOutputFound(output); | ||||
if(outputFound.size() != expectedOutputLines.size()) { | if(outputFound.size() != expectedOutputLines.size()) { | ||||
createFailureMessage(output, -1, outputFound.size()); | createFailureMessage(output, -1, outputFound.size()); | ||||
return; | return; | ||||
} | |||||
} | |||||
List<String> expected = new ArrayList<String>(); | List<String> expected = new ArrayList<String>(); | ||||
expected.addAll(expectedOutputLines); | expected.addAll(expectedOutputLines); | ||||
List<String> found = new ArrayList<String>(); | List<String> found = new ArrayList<String>(); | ||||
found.addAll(outputFound); | found.addAll(outputFound); | ||||
for (Iterator<String> iterator = outputFound.iterator(); iterator.hasNext();) { | for (Iterator<String> iterator = outputFound.iterator(); iterator.hasNext();) { | ||||
String lineFound = (String) iterator.next(); | |||||
String lineFound = iterator.next(); | |||||
for (Iterator<String> iterator2 = expectedOutputLines.iterator(); iterator2.hasNext();) { | for (Iterator<String> iterator2 = expectedOutputLines.iterator(); iterator2.hasNext();) { | ||||
String lineExpected = (String) iterator2.next(); | |||||
String lineExpected = iterator2.next(); | |||||
if (lineFound.indexOf(lineExpected)!= -1) { | if (lineFound.indexOf(lineExpected)!= -1) { | ||||
found.remove(lineFound); | found.remove(lineFound); | ||||
expected.remove(lineExpected); | expected.remove(lineExpected); | ||||
createFailureMessage(output,-2,outputFound.size()); | createFailureMessage(output,-2,outputFound.size()); | ||||
} | } | ||||
} | } | ||||
private void createFailureMessage(String output, int lineNo, int sizeFound) { | private void createFailureMessage(String output, int lineNo, int sizeFound) { | ||||
StringBuffer failMessage = new StringBuffer(); | StringBuffer failMessage = new StringBuffer(); | ||||
failMessage.append("\n expecting output:\n"); | failMessage.append("\n expecting output:\n"); | ||||
for (String line: expectedOutputLines) { | for (String line: expectedOutputLines) { | ||||
failMessage.append(line); | |||||
failMessage.append("\n"); | failMessage.append("\n"); | ||||
} | } | ||||
failMessage.append(" but found output:\n"); | failMessage.append(" but found output:\n"); | ||||
failMessage.append("First difference is on line " + lineNo); | failMessage.append("First difference is on line " + lineNo); | ||||
} | } | ||||
failMessage.append("\n"); | failMessage.append("\n"); | ||||
AjcTestCase.fail(failMessage.toString()); | |||||
AjcTestCase.fail(failMessage.toString()); | |||||
} | } | ||||
private List<String> getOutputFound(String output) { | private List<String> getOutputFound(String output) { | ||||
List<String> found = new ArrayList<String>(); | List<String> found = new ArrayList<String>(); | ||||
StringTokenizer strTok = new StringTokenizer(output,"\n"); | StringTokenizer strTok = new StringTokenizer(output,"\n"); |
package foo; | |||||
import java.sql.SQLException; | |||||
public class Application { | |||||
public static void main(String[] args) throws SQLException { | |||||
System.out.println("Aspect should not kick in without ITD, but should with ITD"); | |||||
new BaseClass().getConnection(); | |||||
new BaseClass().getConnection("user", "pw"); | |||||
System.out.println("Aspect should kick in"); | |||||
new SubClass().getConnection(); | |||||
new SubClass().getConnection("user", "pw"); | |||||
} | |||||
} |
package foo; | |||||
import java.io.PrintWriter; | |||||
import java.sql.Connection; | |||||
import java.sql.SQLException; | |||||
import java.sql.SQLFeatureNotSupportedException; | |||||
import java.util.logging.Logger; | |||||
public class BaseClass { | |||||
public PrintWriter getLogWriter() throws SQLException { return null; } | |||||
public void setLogWriter(PrintWriter out) throws SQLException {} | |||||
public void setLoginTimeout(int seconds) throws SQLException {} | |||||
public int getLoginTimeout() throws SQLException { return 0; } | |||||
public Logger getParentLogger() throws SQLFeatureNotSupportedException { return null; } | |||||
public <T> T unwrap(Class<T> iface) throws SQLException { return null; } | |||||
public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; } | |||||
public Connection getConnection() throws SQLException { return null; } | |||||
public Connection getConnection(String username, String password) throws SQLException { return null; } | |||||
} |
public class Code { | |||||
public static void main(String[] argv) { | |||||
} | |||||
static aspect X { | |||||
before(): execution(* Code.main(..)) { | |||||
System.out.println( | |||||
""" | |||||
This | |||||
is | |||||
on | |||||
multiple | |||||
lines | |||||
""" | |||||
); | |||||
} | |||||
} | |||||
} |
package foo; | |||||
import javax.sql.DataSource; | |||||
import org.aspectj.lang.JoinPoint; | |||||
import org.aspectj.lang.annotation.Aspect; | |||||
import org.aspectj.lang.annotation.Before; | |||||
import org.aspectj.lang.annotation.DeclareParents; | |||||
@Aspect | |||||
public class DataSourceConnectionAspectAnno { | |||||
// This statement crashes the AspectJ compiler | |||||
@DeclareParents("foo.BaseClass") | |||||
private DataSource dataSource; | |||||
@Before("execution(public java.sql.Connection javax.sql.DataSource+.getConnection(..))") | |||||
public void myAdvice(JoinPoint thisJoinPoint) { | |||||
System.out.println(thisJoinPoint); | |||||
} | |||||
} |
package foo; | |||||
import javax.sql.DataSource; | |||||
import org.aspectj.lang.JoinPoint; | |||||
import org.aspectj.lang.annotation.Aspect; | |||||
import org.aspectj.lang.annotation.Before; | |||||
import org.aspectj.lang.annotation.DeclareParents; | |||||
import javax.sql.DataSource; | |||||
public aspect DataSourceConnectionAspectCode { | |||||
declare parents: BaseClass implements DataSource; | |||||
before() : execution(public java.sql.Connection javax.sql.DataSource+.getConnection(..)) { | |||||
System.out.println(thisJoinPoint); | |||||
} | |||||
} |
package foo; | |||||
import javax.sql.DataSource; | |||||
public class SubClass extends BaseClass implements DataSource {} |
*/ | */ | ||||
public class Ajc195Tests extends XMLBasedAjcTestCase { | public class Ajc195Tests extends XMLBasedAjcTestCase { | ||||
public void testAtDecpNPE_code_550494() { | |||||
runTest("at decp npe - code"); | |||||
} | |||||
public void testAtDecpNPE_anno_550494() { | |||||
runTest("at decp npe - anno"); | |||||
} | |||||
public void testAvoidWeavingSwitchInfrastructure() { | public void testAvoidWeavingSwitchInfrastructure() { | ||||
runTest("avoid weaving switch infrastructure"); | runTest("avoid weaving switch infrastructure"); | ||||
} | } |
<suite> | <suite> | ||||
<ajc-test dir="bugs195/550494" vm="1.8" title="at decp npe - code"> | |||||
<compile files="Application.java BaseClass.java SubClass.java DataSourceConnectionAspectCode.java" options="-1.8"/> | |||||
<run class="foo.Application"> | |||||
<stdout> | |||||
<line text="Aspect should not kick in without ITD, but should with ITD"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection())"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection(String, String))"/> | |||||
<line text="Aspect should kick in"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection())"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection(String, String))"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs195/550494" vm="1.8" title="at decp npe - anno"> | |||||
<compile files="Application.java BaseClass.java SubClass.java DataSourceConnectionAspectAnno.java" options="-1.8"/> | |||||
<run class="foo.Application"> | |||||
<stdout> | |||||
<line text="Aspect should not kick in without ITD, but should with ITD"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection())"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection(String, String))"/> | |||||
<line text="Aspect should kick in"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection())"/> | |||||
<line text="execution(Connection foo.BaseClass.getConnection(String, String))"/> | |||||
</stdout> | |||||
</run> | |||||
</ajc-test> | |||||
<ajc-test dir="bugs195/333274" vm="1.8" title="around finally blocks and unlinking"> | <ajc-test dir="bugs195/333274" vm="1.8" title="around finally blocks and unlinking"> | ||||
<compile files="Code.java" options="-showWeaveInfo -1.8 -XnoInline"> | <compile files="Code.java" options="-showWeaveInfo -1.8 -XnoInline"> | ||||
<message kind="weave" text="Join point 'method-call(void Code.print2(java.lang.String))' in Type 'Code' (Code.java:15) advised by around advice from 'Azpect' (Code.java:35)"/> | <message kind="weave" text="Join point 'method-call(void Code.print2(java.lang.String))' in Type 'Code' (Code.java:15) advised by around advice from 'Azpect' (Code.java:35)"/> |
/** | /** | ||||
* Annotation defined aspect reader. Reads the Java 5 annotations and turns them into AjAttributes | * Annotation defined aspect reader. Reads the Java 5 annotations and turns them into AjAttributes | ||||
* | |||||
* | |||||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | ||||
*/ | */ | ||||
public class AtAjAttributes { | public class AtAjAttributes { | ||||
/** | /** | ||||
* A struct when we read @AJ on method | * A struct when we read @AJ on method | ||||
* | |||||
* | |||||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | ||||
*/ | */ | ||||
private static class AjAttributeMethodStruct extends AjAttributeStruct { | private static class AjAttributeMethodStruct extends AjAttributeStruct { | ||||
/** | /** | ||||
* Annotations are RuntimeVisible only. This allow us to not visit RuntimeInvisible ones. | * Annotations are RuntimeVisible only. This allow us to not visit RuntimeInvisible ones. | ||||
* | |||||
* | |||||
* @param attribute | * @param attribute | ||||
* @return true if runtime visible annotation | * @return true if runtime visible annotation | ||||
*/ | */ | ||||
/** | /** | ||||
* Extract class level annotations and turn them into AjAttributes. | * Extract class level annotations and turn them into AjAttributes. | ||||
* | |||||
* | |||||
* @param javaClass | * @param javaClass | ||||
* @param type | * @param type | ||||
* @param context | * @param context | ||||
/** | /** | ||||
* Extract method level annotations and turn them into AjAttributes. | * Extract method level annotations and turn them into AjAttributes. | ||||
* | |||||
* | |||||
* @param method | * @param method | ||||
* @param type | * @param type | ||||
* @param context | * @param context | ||||
/** | /** | ||||
* Extract field level annotations and turn them into AjAttributes. | * Extract field level annotations and turn them into AjAttributes. | ||||
* | |||||
* | |||||
* @param field | * @param field | ||||
* @param type | * @param type | ||||
* @param context | * @param context | ||||
/** | /** | ||||
* Read @Aspect | * Read @Aspect | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read a perClause, returns null on failure and issue messages | * Read a perClause, returns null on failure and issue messages | ||||
* | |||||
* | |||||
* @param perClauseString like "pertarget(.....)" | * @param perClauseString like "pertarget(.....)" | ||||
* @param struct for which we are parsing the per clause | * @param struct for which we are parsing the per clause | ||||
* @return a PerClause instance | * @return a PerClause instance | ||||
/** | /** | ||||
* Read @DeclarePrecedence | * Read @DeclarePrecedence | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
// return false; | // return false; | ||||
// } | // } | ||||
/** | |||||
* Read @DeclareParents | |||||
* | |||||
* @param runtimeAnnotations | |||||
* @param struct | |||||
* @return true if found | |||||
*/ | |||||
private static boolean handleDeclareParentsAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeFieldStruct struct) {// , | |||||
// ResolvedPointcutDefinition | |||||
// preResolvedPointcut) | |||||
// { | |||||
AnnotationGen decp = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION); | |||||
if (decp != null) { | |||||
NameValuePair decpPatternNVP = getAnnotationElement(decp, VALUE); | |||||
String decpPattern = decpPatternNVP.getValue().stringifyValue(); | |||||
private static boolean handleDeclareParentsAnnotation(RuntimeAnnos runtimeAnnotations, AjAttributeFieldStruct struct) { | |||||
AnnotationGen decpAnno = getAnnotation(runtimeAnnotations, AjcMemberMaker.DECLAREPARENTS_ANNOTATION); | |||||
if (decpAnno != null) { | |||||
NameValuePair decpPatternNameValuePair = getAnnotationElement(decpAnno, VALUE); | |||||
String decpPattern = decpPatternNameValuePair.getValue().stringifyValue(); | |||||
System.out.println("decpPatterNVP = "+decpPattern); | |||||
if (decpPattern != null) { | if (decpPattern != null) { | ||||
TypePattern typePattern = parseTypePattern(decpPattern, struct); | TypePattern typePattern = parseTypePattern(decpPattern, struct); | ||||
ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve( | ResolvedType fieldType = UnresolvedType.forSignature(struct.field.getSignature()).resolve( | ||||
// do we have a defaultImpl=xxx.class (ie implementation) | // do we have a defaultImpl=xxx.class (ie implementation) | ||||
String defaultImplClassName = null; | String defaultImplClassName = null; | ||||
NameValuePair defaultImplNVP = getAnnotationElement(decp, "defaultImpl"); | |||||
NameValuePair defaultImplNVP = getAnnotationElement(decpAnno, "defaultImpl"); | |||||
if (defaultImplNVP != null) { | if (defaultImplNVP != null) { | ||||
ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue(); | ClassElementValue defaultImpl = (ClassElementValue) defaultImplNVP.getValue(); | ||||
defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName(); | defaultImplClassName = UnresolvedType.forSignature(defaultImpl.getClassString()).getName(); | ||||
} | } | ||||
} | } | ||||
// then iterate on field interface hierarchy (not object) | |||||
boolean hasAtLeastOneMethod = false; | boolean hasAtLeastOneMethod = false; | ||||
// then iterate on field interface hierarchy (not object) | |||||
Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true); | Iterator<ResolvedMember> methodIterator = fieldType.getMethodsIncludingIntertypeDeclarations(false, true); | ||||
while (methodIterator.hasNext()) { | while (methodIterator.hasNext()) { | ||||
ResolvedMember method = methodIterator.next(); | ResolvedMember method = methodIterator.next(); | ||||
/** | /** | ||||
* Process any @DeclareMixin annotation. | * Process any @DeclareMixin annotation. | ||||
* | |||||
* | |||||
* Example Declaration <br> | * Example Declaration <br> | ||||
* | |||||
* | |||||
* @DeclareMixin("Foo+") public I createImpl(Object o) { return new Impl(o); } | * @DeclareMixin("Foo+") public I createImpl(Object o) { return new Impl(o); } | ||||
* | |||||
* | |||||
* <br> | * <br> | ||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
// supplied as a list in the 'Class[] interfaces' value in the annotation value | // supplied as a list in the 'Class[] interfaces' value in the annotation value | ||||
// supplied as just the interface return value of the annotated method | // supplied as just the interface return value of the annotated method | ||||
// supplied as just the class return value of the annotated method | // supplied as just the class return value of the annotated method | ||||
NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces"); | |||||
NameValuePair interfaceListSpecified = getAnnotationElement(declareMixinAnnotation, "interfaces"); | |||||
List<TypePattern> newParents = new ArrayList<TypePattern>(1); | List<TypePattern> newParents = new ArrayList<TypePattern>(1); | ||||
List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1); | List<ResolvedType> newInterfaceTypes = new ArrayList<ResolvedType>(1); | ||||
/** | /** | ||||
* Read @Before | * Read @Before | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read @After | * Read @After | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read @AfterReturning | * Read @AfterReturning | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read @AfterThrowing | * Read @AfterThrowing | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read @Around | * Read @Around | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
/** | /** | ||||
* Read @Pointcut and handle the resolving in a lazy way to deal with pointcut references | * Read @Pointcut and handle the resolving in a lazy way to deal with pointcut references | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if a pointcut was handled | * @return true if a pointcut was handled | ||||
/** | /** | ||||
* Read @DeclareError, @DeclareWarning | * Read @DeclareError, @DeclareWarning | ||||
* | |||||
* | |||||
* @param runtimeAnnotations | * @param runtimeAnnotations | ||||
* @param struct | * @param struct | ||||
* @return true if found | * @return true if found | ||||
* Sets the location for the declare error / warning using the corresponding IProgramElement in the structure model. This will | * Sets the location for the declare error / warning using the corresponding IProgramElement in the structure model. This will | ||||
* only fix bug 120356 if compiled with -emacssym, however, it does mean that the cross references view in AJDT will show the | * only fix bug 120356 if compiled with -emacssym, however, it does mean that the cross references view in AJDT will show the | ||||
* correct information. | * correct information. | ||||
* | |||||
* | |||||
* Other possibilities for fix: 1. using the information in ajcDeclareSoft (if this is set correctly) which will fix the problem | * Other possibilities for fix: 1. using the information in ajcDeclareSoft (if this is set correctly) which will fix the problem | ||||
* if compiled with ajc but not if compiled with javac. 2. creating an AjAttribute called FieldDeclarationLineNumberAttribute | * if compiled with ajc but not if compiled with javac. 2. creating an AjAttribute called FieldDeclarationLineNumberAttribute | ||||
* (much like MethodDeclarationLineNumberAttribute) which we can ask for the offset. This will again only fix bug 120356 when | * (much like MethodDeclarationLineNumberAttribute) which we can ask for the offset. This will again only fix bug 120356 when | ||||
* compiled with ajc. | * compiled with ajc. | ||||
* | |||||
* | |||||
* @param deow | * @param deow | ||||
* @param struct | * @param struct | ||||
*/ | */ | ||||
/** | /** | ||||
* Returns a readable representation of a method. Method.toString() is not suitable. | * Returns a readable representation of a method. Method.toString() is not suitable. | ||||
* | |||||
* | |||||
* @param method | * @param method | ||||
* @return a readable representation of a method | * @return a readable representation of a method | ||||
*/ | */ | ||||
/** | /** | ||||
* Build the bindings for a given method (pointcut / advice) | * Build the bindings for a given method (pointcut / advice) | ||||
* | |||||
* | |||||
* @param struct | * @param struct | ||||
* @return null if no debug info is available | * @return null if no debug info is available | ||||
*/ | */ | ||||
/** | /** | ||||
* Compute the flag for the xxxJoinPoint extra argument | * Compute the flag for the xxxJoinPoint extra argument | ||||
* | |||||
* | |||||
* @param method | * @param method | ||||
* @return extra arg flag | * @return extra arg flag | ||||
*/ | */ | ||||
/** | /** | ||||
* Compute the flag for the xxxJoinPoint extra argument | * Compute the flag for the xxxJoinPoint extra argument | ||||
* | |||||
* | |||||
* @param argumentSignatures | * @param argumentSignatures | ||||
* @return extra arg flag | * @return extra arg flag | ||||
*/ | */ | ||||
/** | /** | ||||
* Returns the runtime (RV/RIV) annotation of type annotationType or null if no such annotation | * Returns the runtime (RV/RIV) annotation of type annotationType or null if no such annotation | ||||
* | |||||
* | |||||
* @param rvs | * @param rvs | ||||
* @param annotationType | * @param annotationType | ||||
* @return annotation | * @return annotation | ||||
/** | /** | ||||
* Returns the value of a given element of an annotation or null if not found Caution: Does not handles default value. | * Returns the value of a given element of an annotation or null if not found Caution: Does not handles default value. | ||||
* | |||||
* | |||||
* @param annotation | * @param annotation | ||||
* @param elementName | * @param elementName | ||||
* @return annotation NVP | * @return annotation NVP | ||||
* Extract the method argument names. First we try the debug info attached to the method (the LocalVariableTable) - if we cannot | * Extract the method argument names. First we try the debug info attached to the method (the LocalVariableTable) - if we cannot | ||||
* find that we look to use the argNames value that may have been supplied on the associated annotation. If that fails we just | * find that we look to use the argNames value that may have been supplied on the associated annotation. If that fails we just | ||||
* don't know and return an empty string. | * don't know and return an empty string. | ||||
* | |||||
* | |||||
* @param method | * @param method | ||||
* @param argNamesFromAnnotation | * @param argNamesFromAnnotation | ||||
* @param methodStruct | * @param methodStruct | ||||
/** | /** | ||||
* A method argument, used for sorting by indexOnStack (ie order in signature) | * A method argument, used for sorting by indexOnStack (ie order in signature) | ||||
* | |||||
* | |||||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | ||||
*/ | */ | ||||
private static class MethodArgument { | private static class MethodArgument { | ||||
/** | /** | ||||
* LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all pointcut referenced before | * LazyResolvedPointcutDefinition lazyly resolve the pointcut so that we have time to register all pointcut referenced before | ||||
* pointcut resolution happens | * pointcut resolution happens | ||||
* | |||||
* | |||||
* @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> | ||||
*/ | */ | ||||
public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition { | public static class LazyResolvedPointcutDefinition extends ResolvedPointcutDefinition { | ||||
/** | /** | ||||
* Helper to test empty strings | * Helper to test empty strings | ||||
* | |||||
* | |||||
* @param s | * @param s | ||||
* @return true if empty or null | * @return true if empty or null | ||||
*/ | */ | ||||
/** | /** | ||||
* Set the pointcut bindings for which to ignore unbound issues, so that we can implicitly bind xxxJoinPoint for @AJ advices | * Set the pointcut bindings for which to ignore unbound issues, so that we can implicitly bind xxxJoinPoint for @AJ advices | ||||
* | |||||
* | |||||
* @param pointcut | * @param pointcut | ||||
* @param bindings | * @param bindings | ||||
*/ | */ | ||||
/** | /** | ||||
* Report an error | * Report an error | ||||
* | |||||
* | |||||
* @param message | * @param message | ||||
* @param location | * @param location | ||||
*/ | */ | ||||
/** | /** | ||||
* Report a warning | * Report a warning | ||||
* | |||||
* | |||||
* @param message | * @param message | ||||
* @param location | * @param location | ||||
*/ | */ | ||||
/** | /** | ||||
* Parse the given pointcut, return null on failure and issue an error | * Parse the given pointcut, return null on failure and issue an error | ||||
* | |||||
* | |||||
* @param pointcutString | * @param pointcutString | ||||
* @param struct | * @param struct | ||||
* @param allowIf | * @param allowIf | ||||
/** | /** | ||||
* Parse the given type pattern, return null on failure and issue an error | * Parse the given type pattern, return null on failure and issue an error | ||||
* | |||||
* | |||||
* @param patternString | * @param patternString | ||||
* @param location | * @param location | ||||
* @return type pattern | * @return type pattern |