From: acolyer Date: Tue, 4 Oct 2005 13:56:38 +0000 (+0000) Subject: itd support in the MAP X-Git-Tag: preDefaultReweavable~2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=b305f9ee512015657cad0ea722b8180d884b1f72;p=aspectj.git itd support in the MAP --- diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/annotation/ajcITD.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/annotation/ajcITD.java new file mode 100644 index 000000000..e67a25f1e --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/annotation/ajcITD.java @@ -0,0 +1,31 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.annotation; + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * @author colyer + * Marker annotation for code style ITDs + * ajc prefix used to indicate that this annotation is *internal* + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ajcITD { + int modifiers(); + String targetType(); + String name(); +} diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/AjTypeImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/AjTypeImpl.java index 7ecebd13b..ca179ad6d 100644 --- a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/AjTypeImpl.java +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/AjTypeImpl.java @@ -29,6 +29,7 @@ import org.aspectj.internal.lang.annotation.ajcDeclareEoW; import org.aspectj.internal.lang.annotation.ajcDeclareParents; import org.aspectj.internal.lang.annotation.ajcDeclarePrecedence; import org.aspectj.internal.lang.annotation.ajcDeclareSoft; +import org.aspectj.internal.lang.annotation.ajcITD; import org.aspectj.internal.lang.annotation.ajcPrivileged; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; @@ -70,6 +71,12 @@ public class AjTypeImpl implements AjType { private Pointcut[] pointcuts = null; private Advice[] declaredAdvice = null; private Advice[] advice = null; + private InterTypeMethodDeclaration[] declaredITDMethods = null; + private InterTypeMethodDeclaration[] itdMethods = null; + private InterTypeFieldDeclaration[] declaredITDFields = null; + private InterTypeFieldDeclaration[] itdFields = null; + private InterTypeConstructorDeclaration[] itdCons = null; + private InterTypeConstructorDeclaration[] declaredITDCons = null; public AjTypeImpl(Class fromClass) { this.clazz = fromClass; @@ -547,101 +554,346 @@ public class AjTypeImpl implements AjType { * @see org.aspectj.lang.reflect.AjType#getDeclaredITDMethod(java.lang.String, java.lang.Class, java.lang.Class...) */ public InterTypeMethodDeclaration getDeclaredITDMethod(String name, - AjType target, AjType... parameterTypes) { - // TODO Auto-generated method stub - return null; + AjType target, AjType... parameterTypes) throws NoSuchMethodException { + InterTypeMethodDeclaration[] itdms = getDeclaredITDMethods(); + outer: for (InterTypeMethodDeclaration itdm : itdms) { + try { + if (!itdm.getName().equals(name)) continue; + AjType itdTarget = itdm.getTargetType(); + if (itdTarget.equals(target)) { + AjType[] ptypes = itdm.getParameterTypes(); + if (ptypes.length == parameterTypes.length) { + for (int i = 0; i < ptypes.length; i++) { + if (!ptypes[i].equals(parameterTypes[i])) + continue outer; + } + return itdm; + } + } + } catch (ClassNotFoundException cnf) { + // just move on to the next one + } + } + throw new NoSuchMethodException(name); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclaredITDMethods() */ public InterTypeMethodDeclaration[] getDeclaredITDMethods() { - // TODO Auto-generated method stub - return null; + if (this.declaredITDMethods == null) { + List itdms = new ArrayList(); + Method[] baseMethods = clazz.getDeclaredMethods(); + for (Method m : baseMethods) { + if (!m.getName().contains("ajc$interMethod$")) continue; + if (m.isAnnotationPresent(ajcITD.class)) { + ajcITD ann = m.getAnnotation(ajcITD.class); + InterTypeMethodDeclaration itdm = + new InterTypeMethodDeclarationImpl( + this,ann.targetType(),ann.modifiers(), + ann.name(),m); + itdms.add(itdm); + } + } + addAnnotationStyleITDMethods(itdms,false); + this.declaredITDMethods = new InterTypeMethodDeclaration[itdms.size()]; + itdms.toArray(this.declaredITDMethods); + } + return this.declaredITDMethods; } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDMethod(java.lang.String, java.lang.Class, java.lang.Class...) */ public InterTypeMethodDeclaration getITDMethod(String name, AjType target, - AjType... parameterTypes) { - // TODO Auto-generated method stub - return null; + AjType... parameterTypes) + throws NoSuchMethodException { + InterTypeMethodDeclaration[] itdms = getITDMethods(); + outer: for (InterTypeMethodDeclaration itdm : itdms) { + try { + if (!itdm.getName().equals(name)) continue; + AjType itdTarget = itdm.getTargetType(); + if (itdTarget.equals(target)) { + AjType[] ptypes = itdm.getParameterTypes(); + if (ptypes.length == parameterTypes.length) { + for (int i = 0; i < ptypes.length; i++) { + if (!ptypes[i].equals(parameterTypes[i])) + continue outer; + } + return itdm; + } + } + } catch (ClassNotFoundException cnf) { + // just move on to the next one + } + } + throw new NoSuchMethodException(name); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDMethods() */ public InterTypeMethodDeclaration[] getITDMethods() { - // TODO Auto-generated method stub - return null; + if (this.itdMethods == null) { + List itdms = new ArrayList(); + Method[] baseMethods = clazz.getDeclaredMethods(); + for (Method m : baseMethods) { + if (!m.getName().contains("ajc$interMethod$")) continue; + if (m.isAnnotationPresent(ajcITD.class)) { + ajcITD ann = m.getAnnotation(ajcITD.class); + if (!Modifier.isPublic(ann.modifiers())) continue; + InterTypeMethodDeclaration itdm = + new InterTypeMethodDeclarationImpl( + this,ann.targetType(),ann.modifiers(), + ann.name(),m); + itdms.add(itdm); + } + } + addAnnotationStyleITDMethods(itdms,true); + this.itdMethods = new InterTypeMethodDeclaration[itdms.size()]; + itdms.toArray(this.itdMethods); + } + return this.itdMethods; + } + + private void addAnnotationStyleITDMethods(List toList, boolean publicOnly) { + if (isAspect()) { + Class[] classes = clazz.getDeclaredClasses(); + for(Class c : classes) { + if (c.isAnnotationPresent(org.aspectj.lang.annotation.DeclareParents.class)) { + if (c.getInterfaces().length == 0) continue; + AjType targetType = AjTypeSystem.getAjType((Class)c.getInterfaces()[0]); + Method[] meths = c.getDeclaredMethods(); + for (Method m : meths) { + if (!Modifier.isPublic(m.getModifiers()) && publicOnly) continue; + InterTypeMethodDeclaration itdm = + new InterTypeMethodDeclarationImpl( + this,targetType,m); + toList.add(itdm); + } + } + } + } } + private void addAnnotationStyleITDFields(List toList, boolean publicOnly) { + if (isAspect()) { + Class[] classes = clazz.getDeclaredClasses(); + for(Class c : classes) { + if (c.isAnnotationPresent(org.aspectj.lang.annotation.DeclareParents.class)) { + if (c.getInterfaces().length == 0) continue; + AjType targetType = AjTypeSystem.getAjType((Class)c.getInterfaces()[0]); + Field[] fields = c.getDeclaredFields(); + for (Field f : fields) { + if (!Modifier.isPublic(f.getModifiers()) && publicOnly) continue; + InterTypeFieldDeclaration itdf = + new InterTypeFieldDeclarationImpl( + this,targetType,f); + toList.add(itdf); + } + } + } + } + } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclaredITDConstructor(java.lang.Class, java.lang.Class...) */ public InterTypeConstructorDeclaration getDeclaredITDConstructor( - AjType target, AjType... parameterTypes) { - // TODO Auto-generated method stub - return null; + AjType target, AjType... parameterTypes) throws NoSuchMethodException { + InterTypeConstructorDeclaration[] itdcs = getDeclaredITDConstructors(); + outer: for (InterTypeConstructorDeclaration itdc : itdcs) { + try { + AjType itdTarget = itdc.getTargetType(); + if (itdTarget.equals(target)) { + AjType[] ptypes = itdc.getParameterTypes(); + if (ptypes.length == parameterTypes.length) { + for (int i = 0; i < ptypes.length; i++) { + if (!ptypes[i].equals(parameterTypes[i])) + continue outer; + } + return itdc; + } + } + } catch (ClassNotFoundException cnf) { + // just move on to the next one + } + } + throw new NoSuchMethodException(); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclaredITDConstructors() */ public InterTypeConstructorDeclaration[] getDeclaredITDConstructors() { - // TODO Auto-generated method stub - return null; + if (this.declaredITDCons == null) { + List itdcs = new ArrayList(); + Method[] baseMethods = clazz.getDeclaredMethods(); + for (Method m : baseMethods) { + if (!m.getName().contains("ajc$postInterConstructor")) continue; + if (m.isAnnotationPresent(ajcITD.class)) { + ajcITD ann = m.getAnnotation(ajcITD.class); + InterTypeConstructorDeclaration itdc = + new InterTypeConstructorDeclarationImpl(this,ann.targetType(),ann.modifiers(),m); + itdcs.add(itdc); + } + } + this.declaredITDCons = new InterTypeConstructorDeclaration[itdcs.size()]; + itdcs.toArray(this.declaredITDCons); + } + return this.declaredITDCons; } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDConstructor(java.lang.Class, java.lang.Class...) */ public InterTypeConstructorDeclaration getITDConstructor(AjType target, - AjType... parameterTypes) { - // TODO Auto-generated method stub - return null; + AjType... parameterTypes) throws NoSuchMethodException { + InterTypeConstructorDeclaration[] itdcs = getITDConstructors(); + outer: for (InterTypeConstructorDeclaration itdc : itdcs) { + try { + AjType itdTarget = itdc.getTargetType(); + if (itdTarget.equals(target)) { + AjType[] ptypes = itdc.getParameterTypes(); + if (ptypes.length == parameterTypes.length) { + for (int i = 0; i < ptypes.length; i++) { + if (!ptypes[i].equals(parameterTypes[i])) + continue outer; + } + return itdc; + } + } + } catch (ClassNotFoundException cnf) { + // just move on to the next one + } + } + throw new NoSuchMethodException(); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDConstructors() */ public InterTypeConstructorDeclaration[] getITDConstructors() { - // TODO Auto-generated method stub - return null; - } + if (this.itdCons == null) { + List itdcs = new ArrayList(); + Method[] baseMethods = clazz.getMethods(); + for (Method m : baseMethods) { + if (!m.getName().contains("ajc$postInterConstructor")) continue; + if (m.isAnnotationPresent(ajcITD.class)) { + ajcITD ann = m.getAnnotation(ajcITD.class); + if (!Modifier.isPublic(ann.modifiers())) continue; + InterTypeConstructorDeclaration itdc = + new InterTypeConstructorDeclarationImpl(this,ann.targetType(),ann.modifiers(),m); + itdcs.add(itdc); + } + } + this.itdCons = new InterTypeConstructorDeclaration[itdcs.size()]; + itdcs.toArray(this.itdCons); + } + return this.itdCons; } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclaredITDField(java.lang.String, java.lang.Class) */ public InterTypeFieldDeclaration getDeclaredITDField(String name, - AjType target) { - // TODO Auto-generated method stub - return null; + AjType target) throws NoSuchFieldException { + InterTypeFieldDeclaration[] itdfs = getDeclaredITDFields(); + for (InterTypeFieldDeclaration itdf : itdfs) { + if (itdf.getName().equals(name)) { + try { + AjType itdTarget = itdf.getTargetType(); + if (itdTarget.equals(target)) return itdf; + } catch (ClassNotFoundException cnfEx) { + // move on to next field + } + } + } + throw new NoSuchFieldException(name); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclaredITDFields() */ public InterTypeFieldDeclaration[] getDeclaredITDFields() { - // TODO Auto-generated method stub - return null; + List itdfs = new ArrayList(); + if (this.declaredITDFields == null) { + Method[] baseMethods = clazz.getDeclaredMethods(); + for(Method m : baseMethods) { + if (m.isAnnotationPresent(ajcITD.class)) { + if (!m.getName().contains("ajc$interFieldInit")) continue; + ajcITD ann = m.getAnnotation(ajcITD.class); + String interFieldInitMethodName = m.getName(); + String interFieldGetDispatchMethodName = + interFieldInitMethodName.replace("FieldInit","FieldGetDispatch"); + try { + Method dispatch = clazz.getDeclaredMethod(interFieldGetDispatchMethodName, m.getParameterTypes()); + InterTypeFieldDeclaration itdf = new InterTypeFieldDeclarationImpl( + this,ann.targetType(),ann.modifiers(),ann.name(), + AjTypeSystem.getAjType(dispatch.getReturnType()), + dispatch.getGenericReturnType()); + itdfs.add(itdf); + } catch (NoSuchMethodException nsmEx) { + throw new IllegalStateException("Can't find field get dispatch method for " + m.getName()); + } + } + } + addAnnotationStyleITDFields(itdfs, false); + this.declaredITDFields = new InterTypeFieldDeclaration[itdfs.size()]; + itdfs.toArray(this.declaredITDFields); + } + return this.declaredITDFields; } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDField(java.lang.String, java.lang.Class) */ - public InterTypeFieldDeclaration getITDField(String name, AjType target) { - // TODO Auto-generated method stub - return null; + public InterTypeFieldDeclaration getITDField(String name, AjType target) + throws NoSuchFieldException { + InterTypeFieldDeclaration[] itdfs = getITDFields(); + for (InterTypeFieldDeclaration itdf : itdfs) { + if (itdf.getName().equals(name)) { + try { + AjType itdTarget = itdf.getTargetType(); + if (itdTarget.equals(target)) return itdf; + } catch (ClassNotFoundException cnfEx) { + // move on to next field + } + } + } + throw new NoSuchFieldException(name); } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getITDFields() */ public InterTypeFieldDeclaration[] getITDFields() { - // TODO Auto-generated method stub - return null; + List itdfs = new ArrayList(); + if (this.itdFields == null) { + Method[] baseMethods = clazz.getMethods(); + for(Method m : baseMethods) { + if (m.isAnnotationPresent(ajcITD.class)) { + ajcITD ann = m.getAnnotation(ajcITD.class); + if (!m.getName().contains("ajc$interFieldInit")) continue; + if (!Modifier.isPublic(ann.modifiers())) continue; + String interFieldInitMethodName = m.getName(); + String interFieldGetDispatchMethodName = + interFieldInitMethodName.replace("FieldInit","FieldGetDispatch"); + try { + Method dispatch = m.getDeclaringClass().getDeclaredMethod(interFieldGetDispatchMethodName, m.getParameterTypes()); + InterTypeFieldDeclaration itdf = new InterTypeFieldDeclarationImpl( + this,ann.targetType(),ann.modifiers(),ann.name(), + AjTypeSystem.getAjType(dispatch.getReturnType()), + dispatch.getGenericReturnType()); + itdfs.add(itdf); + } catch (NoSuchMethodException nsmEx) { + throw new IllegalStateException("Can't find field get dispatch method for " + m.getName()); + } + } + } + addAnnotationStyleITDFields(itdfs, true); + this.itdFields = new InterTypeFieldDeclaration[itdfs.size()]; + itdfs.toArray(this.itdFields); + } + return this.itdFields; } /* (non-Javadoc) @@ -701,6 +953,7 @@ public class AjTypeImpl implements AjType { decps.add(decp); } } + addAnnotationStyleDeclareParents(decps); if (getSupertype().isAspect()) { decps.addAll(Arrays.asList(getSupertype().getDeclareParents())); } @@ -708,6 +961,24 @@ public class AjTypeImpl implements AjType { decps.toArray(ret); return ret; } + + private void addAnnotationStyleDeclareParents(List toList) { + Class[] classes = clazz.getDeclaredClasses(); + for (Class c : classes) { + if (c.isAnnotationPresent(org.aspectj.lang.annotation.DeclareParents.class)) { + org.aspectj.lang.annotation.DeclareParents ann = c.getAnnotation(org.aspectj.lang.annotation.DeclareParents.class); + if (c.getInterfaces().length == 0) continue; + String parentType = c.getInterfaces()[0].getName(); + DeclareParentsImpl decp = new DeclareParentsImpl( + ann.value(), + parentType, + false, + this + ); + toList.add(decp); + } + } + } /* (non-Javadoc) * @see org.aspectj.lang.reflect.AjType#getDeclareSofts() diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/DeclareParentsImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/DeclareParentsImpl.java index 1a04fc507..4f5720667 100644 --- a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/DeclareParentsImpl.java +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/DeclareParentsImpl.java @@ -11,13 +11,9 @@ * ******************************************************************/ package org.aspectj.internal.lang.reflect; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.StringTokenizer; import org.aspectj.lang.reflect.AjType; -import org.aspectj.lang.reflect.AjTypeSystem; import org.aspectj.lang.reflect.DeclareParents; import org.aspectj.lang.reflect.TypePattern; @@ -45,7 +41,12 @@ public class DeclareParentsImpl implements DeclareParents { this.isExtends = isExtends; this.declaringType = declaring; this.parentsString = parentsAsString; - this.parents = commaSeparatedListToTypeArray(parentsAsString); + try { + this.parents = StringToType.commaSeparatedListToTypeArray(parentsAsString, declaring.getJavaClass()); + } catch (ClassNotFoundException cnfEx) { + this.parentsError = true; + this.firstMissingTypeName = cnfEx.getMessage(); + } } /* (non-Javadoc) @@ -85,60 +86,6 @@ public class DeclareParentsImpl implements DeclareParents { } return this.parents; } - - private Type[] commaSeparatedListToTypeArray(String typeNames) { - StringTokenizer strTok = new StringTokenizer(typeNames,","); - Type[] ret = new Type[strTok.countTokens()]; - int index = 0; - outer: while (strTok.hasMoreTokens()) { - String parentTypeName = strTok.nextToken().trim(); - try { - if (parentTypeName.indexOf("<") == -1) { - ret[index] = AjTypeSystem.getAjType(Class.forName(parentTypeName)); - } else { - ret[index] = makeParameterizedType(parentTypeName); - } - } catch (ClassNotFoundException e) { - // could be a type variable - TypeVariable[] tVars = this.declaringType.getJavaClass().getTypeParameters(); - for (int i = 0; i < tVars.length; i++) { - if (tVars[i].getName().equals(parentTypeName)) { - ret[index] = tVars[i]; - continue outer; - } - } - ret[index] = null; - if (this.firstMissingTypeName == null) this.firstMissingTypeName = parentTypeName; - this.parentsError = true; - } - index++; - } - return ret; - } - - private Type makeParameterizedType(String typeName) - throws ClassNotFoundException { - int paramStart = typeName.indexOf('<'); - String baseName = typeName.substring(0, paramStart); - final Class baseClass = Class.forName(baseName); - int paramEnd = typeName.lastIndexOf('>'); - String params = typeName.substring(paramStart+1,paramEnd); - final Type[] typeParams = commaSeparatedListToTypeArray(params); - return new ParameterizedType() { - - public Type[] getActualTypeArguments() { - return typeParams; - } - - public Type getRawType() { - return baseClass; - } - - public Type getOwnerType() { - return baseClass.getEnclosingClass(); - } - }; - } public String toString() { StringBuffer sb = new StringBuffer(); diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeConstructorDeclarationImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeConstructorDeclarationImpl.java new file mode 100644 index 000000000..7a84c7d12 --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeConstructorDeclarationImpl.java @@ -0,0 +1,81 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.AjTypeSystem; +import org.aspectj.lang.reflect.InterTypeConstructorDeclaration; + +/** + * @author colyer + * + */ +public class InterTypeConstructorDeclarationImpl extends + InterTypeDeclarationImpl implements InterTypeConstructorDeclaration { + + private Method baseMethod; + + /** + * @param decType + * @param target + * @param mods + */ + public InterTypeConstructorDeclarationImpl(AjType decType, + String target, int mods, Method baseMethod) { + super(decType, target, mods); + this.baseMethod = baseMethod; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeConstructorDeclaration#getParameters() + */ + public AjType[] getParameterTypes() { + Class[] baseTypes = baseMethod.getParameterTypes(); + AjType[] ret = new AjType[baseTypes.length-1]; + for (int i = 1; i < baseTypes.length; i++) { + ret[i-1] = AjTypeSystem.getAjType(baseTypes[i]); + } + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeConstructorDeclaration#getGenericParameters() + */ + public Type[] getGenericParameterTypes() { + Type[] baseTypes = baseMethod.getGenericParameterTypes(); + Type[] ret = new AjType[baseTypes.length-1]; + for (int i = 1; i < baseTypes.length; i++) { + if (baseTypes[i] instanceof Class) { + ret[i-1] = AjTypeSystem.getAjType((Class)baseTypes[i]); + } else { + ret[i-1] = baseTypes[i]; + } + } + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeConstructorDeclaration#getDeclaredExceptionTypes() + */ + public AjType[] getExceptionTypes() { + Class[] baseTypes = baseMethod.getExceptionTypes(); + AjType[] ret = new AjType[baseTypes.length]; + for (int i = 0; i < baseTypes.length; i++) { + ret[i] = AjTypeSystem.getAjType(baseTypes[i]); + } + return ret; + } + +} diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeDeclarationImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeDeclarationImpl.java new file mode 100644 index 000000000..a3def1030 --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeDeclarationImpl.java @@ -0,0 +1,68 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.InterTypeDeclaration; + +/** + * @author colyer + * + */ +public class InterTypeDeclarationImpl implements InterTypeDeclaration { + + private AjType declaringType; + private String targetTypeName; + private AjType targetType; + private int modifiers; + + public InterTypeDeclarationImpl(AjType decType, String target, int mods) { + this.declaringType = decType; + this.targetTypeName = target; + this.modifiers = mods; + try { + this.targetType = (AjType) StringToType.stringToType(target, decType.getJavaClass()); + } catch (ClassNotFoundException cnf) { + // we'll only report this later if the user asks for the target type. + } + } + + public InterTypeDeclarationImpl(AjType decType, AjType targetType, int mods) { + this.declaringType = decType; + this.targetType = targetType; + this.targetTypeName = targetType.getName(); + this.modifiers = mods; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeDeclaration#getDeclaringType() + */ + public AjType getDeclaringType() { + return this.declaringType; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeDeclaration#getTargetType() + */ + public AjType getTargetType() throws ClassNotFoundException { + if (this.targetType == null) throw new ClassNotFoundException(this.targetTypeName); + return this.targetType; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeDeclaration#getModifiers() + */ + public int getModifiers() { + return this.modifiers; + } + +} diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeFieldDeclarationImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeFieldDeclarationImpl.java new file mode 100644 index 000000000..5cca0b360 --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeFieldDeclarationImpl.java @@ -0,0 +1,78 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; + +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.AjTypeSystem; +import org.aspectj.lang.reflect.InterTypeFieldDeclaration; + +/** + * @author colyer + * + */ +public class InterTypeFieldDeclarationImpl extends InterTypeDeclarationImpl + implements InterTypeFieldDeclaration { + + private String name; + private AjType type; + private Type genericType; + + /** + * @param decType + * @param target + * @param mods + */ + public InterTypeFieldDeclarationImpl(AjType decType, String target, + int mods, String name, AjType type, Type genericType) { + super(decType, target, mods); + this.name = name; + this.type = type; + this.genericType = genericType; + } + + public InterTypeFieldDeclarationImpl(AjType decType, AjType targetType, Field base) { + super(decType,targetType,base.getModifiers()); + this.name = base.getName(); + this.type = AjTypeSystem.getAjType(base.getType()); + Type gt = base.getGenericType(); + if (gt instanceof Class) { + this.genericType = AjTypeSystem.getAjType((Class)gt); + } else { + this.genericType = gt; + } + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeFieldDeclaration#getName() + */ + public String getName() { + return this.name; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeFieldDeclaration#getType() + */ + public AjType getType() { + return this.type; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeFieldDeclaration#getGenericType() + */ + public Type getGenericType() { + return this.genericType; + } + +} diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeMethodDeclarationImpl.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeMethodDeclarationImpl.java new file mode 100644 index 000000000..25688441d --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/InterTypeMethodDeclarationImpl.java @@ -0,0 +1,126 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.AjTypeSystem; +import org.aspectj.lang.reflect.InterTypeMethodDeclaration; + +/** + * @author colyer + * + */ +public class InterTypeMethodDeclarationImpl extends InterTypeDeclarationImpl + implements InterTypeMethodDeclaration { + + private String name; + private Method baseMethod; + private int parameterAdjustmentFactor = 1; // no of fake params at start of baseMethod + private AjType[] parameterTypes; + private Type[] genericParameterTypes; + private AjType returnType; + private Type genericReturnType; + private AjType[] exceptionTypes; + + /** + * @param decType + * @param target + * @param mods + */ + public InterTypeMethodDeclarationImpl(AjType decType, String target, + int mods, String name, Method itdInterMethod) { + super(decType, target, mods); + this.name = name; + this.baseMethod = itdInterMethod; + } + + public InterTypeMethodDeclarationImpl(AjType decType, AjType targetType, Method base) { + super(decType,targetType,base.getModifiers()); + this.parameterAdjustmentFactor = 0; + this.name = base.getName(); + this.baseMethod = base; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getName() + */ + public String getName() { + return this.name; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getReturnType() + */ + public AjType getReturnType() { + return AjTypeSystem.getAjType(baseMethod.getReturnType()); + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getGenericReturnType() + */ + public Type getGenericReturnType() { + Type gRet = baseMethod.getGenericReturnType(); + if (gRet instanceof Class) { + return AjTypeSystem.getAjType((Class)gRet); + } + return gRet; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getParameters() + */ + public AjType[] getParameterTypes() { + Class[] baseTypes = baseMethod.getParameterTypes(); + AjType[] ret = new AjType[baseTypes.length -parameterAdjustmentFactor]; + for (int i = parameterAdjustmentFactor; i < baseTypes.length; i++) { + ret[i-parameterAdjustmentFactor] = AjTypeSystem.getAjType(baseTypes[i]); + } + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getGenericParameters() + */ + public Type[] getGenericParameterTypes() { + Type[] baseTypes = baseMethod.getGenericParameterTypes(); + Type[] ret = new AjType[baseTypes.length-parameterAdjustmentFactor]; + for (int i = parameterAdjustmentFactor; i < baseTypes.length; i++) { + if (baseTypes[i] instanceof Class) { + ret[i-parameterAdjustmentFactor] = AjTypeSystem.getAjType((Class)baseTypes[i]); + } else { + ret[i-parameterAdjustmentFactor] = baseTypes[i]; + } + } + return ret; + } + + /* (non-Javadoc) + * @see org.aspectj.lang.reflect.InterTypeMethodDeclaration#getTypeParameters() + */ + public TypeVariable[] getTypeParameters() { + return baseMethod.getTypeParameters(); + } + + public AjType[] getExceptionTypes() { + Class[] baseTypes = baseMethod.getExceptionTypes(); + AjType[] ret = new AjType[baseTypes.length]; + for (int i = 0; i < baseTypes.length; i++) { + ret[i] = AjTypeSystem.getAjType(baseTypes[i]); + } + return ret; + } + +} diff --git a/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/StringToType.java b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/StringToType.java new file mode 100644 index 000000000..7cf35ffb7 --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/internal/lang/reflect/StringToType.java @@ -0,0 +1,82 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.StringTokenizer; + +import org.aspectj.lang.reflect.AjTypeSystem; + +/** + * @author colyer + * Helper class for converting type representations in Strings into java.lang.reflect.Types. + */ +public class StringToType { + + public static Type[] commaSeparatedListToTypeArray(String typeNames, Class classScope) + throws ClassNotFoundException { + StringTokenizer strTok = new StringTokenizer(typeNames,","); + Type[] ret = new Type[strTok.countTokens()]; + int index = 0; + outer: while (strTok.hasMoreTokens()) { + String typeName = strTok.nextToken().trim(); + ret[index++] = stringToType(typeName, classScope); + } + return ret; + } + + public static Type stringToType(String typeName, Class classScope) + throws ClassNotFoundException { + try { + if (typeName.indexOf("<") == -1) { + return AjTypeSystem.getAjType(Class.forName(typeName)); + } else { + return makeParameterizedType(typeName,classScope); + } + } catch (ClassNotFoundException e) { + // could be a type variable + TypeVariable[] tVars = classScope.getTypeParameters(); + for (int i = 0; i < tVars.length; i++) { + if (tVars[i].getName().equals(typeName)) { + return tVars[i]; + } + } + throw new ClassNotFoundException(typeName); + } + } + + private static Type makeParameterizedType(String typeName, Class classScope) + throws ClassNotFoundException { + int paramStart = typeName.indexOf('<'); + String baseName = typeName.substring(0, paramStart); + final Class baseClass = Class.forName(baseName); + int paramEnd = typeName.lastIndexOf('>'); + String params = typeName.substring(paramStart+1,paramEnd); + final Type[] typeParams = commaSeparatedListToTypeArray(params,classScope); + return new ParameterizedType() { + + public Type[] getActualTypeArguments() { + return typeParams; + } + + public Type getRawType() { + return baseClass; + } + + public Type getOwnerType() { + return baseClass.getEnclosingClass(); + } + }; + } +} diff --git a/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareParents.java b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareParents.java new file mode 100644 index 000000000..3dec04f27 --- /dev/null +++ b/aspectj5rt/java5-src/org/aspectj/lang/annotation/DeclareParents.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * initial implementation Adrian Colyer + *******************************************************************************/ +package org.aspectj.lang.annotation; + +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Declare parents mixin annotation + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface DeclareParents { + + /** + * The target types expression + */ + String value(); + +} diff --git a/aspectj5rt/java5-src/org/aspectj/lang/reflect/AjType.java b/aspectj5rt/java5-src/org/aspectj/lang/reflect/AjType.java index e2db1407f..5e26a7d27 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/reflect/AjType.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/reflect/AjType.java @@ -224,7 +224,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the inter-type method declared by this type matching the given specification */ - public InterTypeMethodDeclaration getDeclaredITDMethod(String name, AjType target, AjType... parameterTypes); + public InterTypeMethodDeclaration getDeclaredITDMethod(String name, AjType target, AjType... parameterTypes) throws NoSuchMethodException; /** * Return all of the inter-type methods declared by this type @@ -234,7 +234,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the public inter-type method of this type matching the given specification */ - public InterTypeMethodDeclaration getITDMethod(String name, AjType target, AjType... parameterTypes); + public InterTypeMethodDeclaration getITDMethod(String name, AjType target, AjType... parameterTypes) throws NoSuchMethodException; /** * Return all of the public inter-type declared methods of this type @@ -244,7 +244,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the inter-type constructor declared by this type matching the given specification */ - public InterTypeConstructorDeclaration getDeclaredITDConstructor(AjType target, AjType... parameterTypes); + public InterTypeConstructorDeclaration getDeclaredITDConstructor(AjType target, AjType... parameterTypes) throws NoSuchMethodException; /** * Returns all of the inter-type constructors declared by this type @@ -254,7 +254,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the public inter-type constructor matching the given specification */ - public InterTypeConstructorDeclaration getITDConstructor(AjType target, AjType... parameterTypes); + public InterTypeConstructorDeclaration getITDConstructor(AjType target, AjType... parameterTypes) throws NoSuchMethodException; /** * Return all of the public inter-type constructors of this type @@ -264,7 +264,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the inter-type field declared in this type with the given specification */ - public InterTypeFieldDeclaration getDeclaredITDField(String name, AjType target); + public InterTypeFieldDeclaration getDeclaredITDField(String name, AjType target) throws NoSuchFieldException; /** * Return all of the inter-type fields declared in this type @@ -274,7 +274,7 @@ public interface AjType extends Type, AnnotatedElement { /** * Return the public inter-type field matching the given specification */ - public InterTypeFieldDeclaration getITDField(String name, AjType target); + public InterTypeFieldDeclaration getITDField(String name, AjType target) throws NoSuchFieldException; /** * Return all of the public inter-type fields for this type diff --git a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeConstructorDeclaration.java b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeConstructorDeclaration.java index d20440a83..8db4505e3 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeConstructorDeclaration.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeConstructorDeclaration.java @@ -11,10 +11,26 @@ * ******************************************************************/ package org.aspectj.lang.reflect; +import java.lang.reflect.Type; + /** - * @author colyer - * + * Runtime representation of an inter-type constructor member declared within an + * aspect. */ public interface InterTypeConstructorDeclaration extends InterTypeDeclaration { + /** + * The constructor parameters + */ + AjType[] getParameterTypes(); + + /** + * The generic constructor parameters + */ + Type[] getGenericParameterTypes(); + + /** + * The declared exceptions thrown by this constructor + */ + AjType[] getExceptionTypes(); } diff --git a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeDeclaration.java b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeDeclaration.java index 510135813..c00461011 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeDeclaration.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeDeclaration.java @@ -11,6 +11,23 @@ * ******************************************************************/ package org.aspectj.lang.reflect; +/** + * Represents an inter-type method, field, or constructor declared in an aspect. + */ public interface InterTypeDeclaration { + /** + * The declaring aspect + */ + AjType getDeclaringType(); + + /** + * The target type of this ITD + */ + AjType getTargetType() throws ClassNotFoundException; + + /** + * Member modifiers, can be interpreted using java.lang.reflect.Modifier + */ + int getModifiers(); } diff --git a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeFieldDeclaration.java b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeFieldDeclaration.java index 99045798c..5a8acd76c 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeFieldDeclaration.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeFieldDeclaration.java @@ -11,10 +11,26 @@ * ******************************************************************/ package org.aspectj.lang.reflect; +import java.lang.reflect.Type; + /** - * @author colyer - * + * Represents an inter-type field declaration declared in an aspect. */ -public interface InterTypeFieldDeclaration { +public interface InterTypeFieldDeclaration extends InterTypeDeclaration { + + /** + * The field name + */ + String getName(); + + /** + * The field type + */ + AjType getType(); + + /** + * The generic field type + */ + Type getGenericType(); } diff --git a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeMethodDeclaration.java b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeMethodDeclaration.java index 3fac5c186..e570d8d2d 100644 --- a/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeMethodDeclaration.java +++ b/aspectj5rt/java5-src/org/aspectj/lang/reflect/InterTypeMethodDeclaration.java @@ -11,6 +11,47 @@ * ******************************************************************/ package org.aspectj.lang.reflect; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +/** + * Represents an inter-type method declaration member within an aspect. + */ public interface InterTypeMethodDeclaration extends InterTypeDeclaration { + /** + * The name of this method + */ + String getName(); + + /** + * The method return type + */ + AjType getReturnType(); + + /** + * The generic return type + */ + Type getGenericReturnType(); + + /** + * The method parameters + */ + AjType[] getParameterTypes(); + + /** + * The generic method parameters + */ + Type[] getGenericParameterTypes(); + + /** + * The type variables declared by this method + */ + TypeVariable[] getTypeParameters(); + + /** + * The declared exceptions thrown by this method + */ + AjType[] getExceptionTypes(); } diff --git a/aspectj5rt/java5-testsrc/Aspectj5rt15ModuleTests.java b/aspectj5rt/java5-testsrc/Aspectj5rt15ModuleTests.java index b0ab7d1fe..c1d54dc67 100644 --- a/aspectj5rt/java5-testsrc/Aspectj5rt15ModuleTests.java +++ b/aspectj5rt/java5-testsrc/Aspectj5rt15ModuleTests.java @@ -18,6 +18,7 @@ import junit.framework.TestSuite; import org.aspectj.internal.lang.reflect.AjTypeTests; import org.aspectj.internal.lang.reflect.AjTypeTestsWithAspects; +import org.aspectj.internal.lang.reflect.InterTypeTests; public class Aspectj5rt15ModuleTests extends TestCase { @@ -25,6 +26,7 @@ public class Aspectj5rt15ModuleTests extends TestCase { TestSuite suite = new TestSuite("Aspectj5rt module tests"); suite.addTestSuite(AjTypeTests.class); suite.addTestSuite(AjTypeTestsWithAspects.class); + suite.addTestSuite(InterTypeTests.class); return suite; } diff --git a/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java index 7b15d3e64..d2fad06b0 100644 --- a/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java +++ b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/AjTypeTestsWithAspects.java @@ -17,6 +17,7 @@ import java.lang.reflect.Modifier; import junit.framework.TestCase; import org.aspectj.internal.lang.annotation.ajcDeclareEoW; +import org.aspectj.internal.lang.annotation.ajcITD; import org.aspectj.internal.lang.annotation.ajcPrivileged; import org.aspectj.lang.annotation.AdviceName; import org.aspectj.lang.annotation.After; diff --git a/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/InterTypeTests.java b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/InterTypeTests.java new file mode 100644 index 000000000..ae7939bb6 --- /dev/null +++ b/aspectj5rt/java5-testsrc/org/aspectj/internal/lang/reflect/InterTypeTests.java @@ -0,0 +1,88 @@ +/* ******************************************************************* + * Copyright (c) 2005 Contributors. + * 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://eclipse.org/legal/epl-v10.html + * + * Contributors: + * Adrian Colyer Initial implementation + * ******************************************************************/ +package org.aspectj.internal.lang.reflect; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import org.aspectj.lang.reflect.AjType; +import org.aspectj.lang.reflect.AjTypeSystem; +import org.aspectj.lang.reflect.InterTypeConstructorDeclaration; +import org.aspectj.lang.reflect.InterTypeDeclaration; +import org.aspectj.lang.reflect.InterTypeFieldDeclaration; +import org.aspectj.lang.reflect.InterTypeMethodDeclaration; + +import junit.framework.TestCase; + +/** + * @author colyer + * + */ +public class InterTypeTests extends TestCase { + + public void testITDImpl() throws ClassNotFoundException { + AjType thisClass = AjTypeSystem.getAjType(InterTypeTests.class); + AjType runnable = AjTypeSystem.getAjType(java.lang.Runnable.class); + InterTypeDeclaration itd = new InterTypeDeclarationImpl(thisClass,"java.lang.Runnable",5); + assertEquals(thisClass,itd.getDeclaringType()); + assertEquals(runnable,itd.getTargetType()); + assertEquals(5, itd.getModifiers()); + } + + public void testITDField() throws ClassNotFoundException { + AjType thisClass = AjTypeSystem.getAjType(InterTypeTests.class); + AjType runnable = AjTypeSystem.getAjType(java.lang.Runnable.class); + InterTypeDeclaration itd = new InterTypeDeclarationImpl(thisClass,"java.lang.Runnable",5); + AjType stringType = AjTypeSystem.getAjType(java.lang.String.class); + Type t = Type.class; + InterTypeFieldDeclaration itdf = new InterTypeFieldDeclarationImpl(thisClass,"java.lang.Runnable",5,"f",stringType,t); + assertEquals("f",itdf.getName()); + assertEquals(stringType,itdf.getType()); + assertEquals(t,itdf.getGenericType()); + } + + public void testITDCons() throws ClassNotFoundException, NoSuchMethodException { + AjType thisClass = AjTypeSystem.getAjType(InterTypeTests.class); + AjType runnable = AjTypeSystem.getAjType(java.lang.Runnable.class); + Method base = InterTypeTests.class.getDeclaredMethod("interCons",InterTypeTests.class,String.class,int.class); + InterTypeConstructorDeclaration itdc = + new InterTypeConstructorDeclarationImpl(thisClass,"java.lang.Runnable",5,base); + assertEquals(2,itdc.getParameterTypes().length); + assertEquals(String.class,itdc.getParameterTypes()[0].getJavaClass()); + assertEquals(int.class,itdc.getParameterTypes()[1].getJavaClass()); + assertEquals(2,itdc.getGenericParameterTypes().length); + assertEquals(base.getGenericParameterTypes()[1],((AjType)itdc.getGenericParameterTypes()[0]).getJavaClass()); + assertEquals(base.getGenericParameterTypes()[2],((AjType)itdc.getGenericParameterTypes()[1]).getJavaClass()); + assertEquals(0,itdc.getExceptionTypes().length); + } + + public void testITDMethod() throws NoSuchMethodException { + AjType thisClass = AjTypeSystem.getAjType(InterTypeTests.class); + AjType runnable = AjTypeSystem.getAjType(java.lang.Runnable.class); + Method base = InterTypeTests.class.getDeclaredMethod("interMethod",InterTypeTests.class,String.class,int.class); + InterTypeMethodDeclaration itdm = new InterTypeMethodDeclarationImpl(thisClass,"java.lang.Runnable",5,"foo",base); + assertEquals("foo",itdm.getName()); + assertEquals(int.class,itdm.getReturnType().getJavaClass()); + assertEquals(int.class,((AjType)itdm.getGenericReturnType()).getJavaClass()); + assertEquals(2,itdm.getParameterTypes().length); + assertEquals(String.class,itdm.getParameterTypes()[0].getJavaClass()); + assertEquals(int.class,itdm.getParameterTypes()[1].getJavaClass()); + assertEquals(2,itdm.getGenericParameterTypes().length); + assertEquals(base.getGenericParameterTypes()[1],((AjType)itdm.getGenericParameterTypes()[0]).getJavaClass()); + assertEquals(base.getGenericParameterTypes()[2],((AjType)itdm.getGenericParameterTypes()[1]).getJavaClass()); + assertEquals(0,itdm.getExceptionTypes().length); + } + + public static void interCons(InterTypeTests itt, String s, int i) { } + + public static int interMethod(InterTypeTests itt, String s, int i) { return 5; } +} diff --git a/lib/aspectj/lib/aspectjrt.jar b/lib/aspectj/lib/aspectjrt.jar index 9c65f72d7..0dbc1d49b 100644 Binary files a/lib/aspectj/lib/aspectjrt.jar and b/lib/aspectj/lib/aspectjrt.jar differ diff --git a/lib/test/aspectjrt.jar b/lib/test/aspectjrt.jar index 9c65f72d7..0dbc1d49b 100644 Binary files a/lib/test/aspectjrt.jar and b/lib/test/aspectjrt.jar differ diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java index 35ae2fb9b..bc709cc2b 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AddAtAspectJAnnotationsVisitor.java @@ -67,6 +67,8 @@ public class AddAtAspectJAnnotationsVisitor extends ASTVisitor { ((PointcutDeclaration)methodDeclaration).addAtAspectJAnnotations(); } else if (methodDeclaration instanceof DeclareDeclaration) { ((DeclareDeclaration)methodDeclaration).addAtAspectJAnnotations(); + } else if (methodDeclaration instanceof InterTypeDeclaration) { + ((InterTypeDeclaration)methodDeclaration).addAtAspectJAnnotations(); } return false; } diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java index 79fdb87be..35fccc856 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/AtAspectJAnnotationFactory.java @@ -13,6 +13,7 @@ package org.aspectj.ajdt.internal.compiler.ast; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.IntLiteral; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; @@ -49,6 +50,7 @@ public class AtAspectJAnnotationFactory { static final char[] declareSoft = "ajcDeclareSoft".toCharArray(); static final char[] declarePrecedence = "ajcDeclarePrecedence".toCharArray(); static final char[] declareAnnotation = "ajcDeclareAnnotation".toCharArray(); + static final char[] itdAnnotation = "ajcITD".toCharArray(); /** * Create an @Aspect annotation for a code style aspect declaration starting at @@ -210,6 +212,23 @@ public class AtAspectJAnnotationFactory { return ann; } + public static Annotation createITDAnnotation(char[] targetTypeName, int modifiers, char[] name, int pos) { + char[][] typeName = new char[][] {org,aspectj,internal,lang,annotation,itdAnnotation}; + long[] positions = new long[typeName.length]; + for (int i = 0; i < positions.length; i++) positions[i] = pos; + TypeReference annType = new QualifiedTypeReference(typeName,positions); + NormalAnnotation ann = new NormalAnnotation(annType,pos); + Expression targetExpr = new StringLiteral(targetTypeName,pos,pos); + Expression nameExpr = new StringLiteral(name,pos,pos); + Expression modsExpr = new IntLiteral(Integer.toString(modifiers).toCharArray(),pos,pos); + MemberValuePair[] mvps = new MemberValuePair[3]; + mvps[0] = new MemberValuePair("targetType".toCharArray(),pos,pos,targetExpr); + mvps[1] = new MemberValuePair("name".toCharArray(),pos,pos,nameExpr); + mvps[2] = new MemberValuePair("modifiers".toCharArray(),pos,pos,modsExpr); + ann.memberValuePairs = mvps; + return ann; + } + public static Annotation createDeclarePrecedenceAnnotation(String pointcutExpression, int pos) { char[][] typeName = new char[][] {org,aspectj,internal,lang,annotation,declarePrecedence}; return makeSingleStringMemberAnnotation(typeName, pos, pointcutExpression); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java index 81c47a4d9..bd159aa17 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/internal/compiler/ast/InterTypeDeclaration.java @@ -26,6 +26,7 @@ import org.aspectj.bridge.context.ContextToken; import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile; import org.aspectj.org.eclipse.jdt.internal.compiler.CompilationResult; +import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleTypeReference; import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference; @@ -93,6 +94,15 @@ public abstract class InterTypeDeclaration extends AjMethodDeclaration { // return the selector prefix for this itd that is to be used before resolution replaces it with a "proper" name protected abstract char[] getPrefix(); + + public void addAtAspectJAnnotations() { + if (munger == null) return; + Annotation ann = AtAspectJAnnotationFactory.createITDAnnotation( + munger.getSignature().getDeclaringType().getName().toCharArray(), + declaredModifiers,declaredSelector,declarationSourceStart); + AtAspectJAnnotationFactory.addAnnotation(this,ann,this.scope); + } + /** * Checks that the target for the ITD is not an annotation. If it is, an error message * is signaled. We return true if it is annotation so the caller knows to stop processing. diff --git a/tests/java5/ataspectj/annotationGen/ITDTest.aj b/tests/java5/ataspectj/annotationGen/ITDTest.aj new file mode 100644 index 000000000..841af326b --- /dev/null +++ b/tests/java5/ataspectj/annotationGen/ITDTest.aj @@ -0,0 +1,181 @@ +package a.b.c; + +import org.aspectj.lang.reflect.*; +import java.lang.reflect.*; +import org.aspectj.lang.annotation.*; + +public aspect ITDTest { + + public void A.a(String s) {} + + private void A.b(String s) {} + + int A.c(String s) { return 1; } + + public A.new(String s) {} + + private A.new(String s,String s2) {} + + A.new(String s, Object o) {} + + public int A.f ; + + private int A.g; + + int A.h; + + public static void main(String[] args) throws ClassNotFoundException { + AjType myType = AjTypeSystem.getAjType(ITDTest.class); + checkITDMs(myType); + checkITDFs(myType); + checkITDCs(myType); + checkAnnStyle(); + } + + private static void checkITDMs(AjType itdTest) throws ClassNotFoundException { + InterTypeMethodDeclaration[] itdms = itdTest.getDeclaredITDMethods(); + assertEquals("expecting 3 declared methods, got: ",3,itdms.length); + assertEquals("expecting method name a, got: ","a",itdms[0].getName()); + assertEquals("expecting method name b, got: ","b",itdms[1].getName()); + assertEquals("expecting method name c, got: ","c",itdms[2].getName()); + assertEquals("expecting AjType",AjTypeSystem.getAjType(A.class),itdms[0].getTargetType()); + assertEquals("expecting public method, got:",true,Modifier.isPublic(itdms[0].getModifiers())); + assertEquals("expecting private method, got:",true,Modifier.isPrivate(itdms[1].getModifiers())); + assertEquals("expecting non-public method, got:",false,Modifier.isPublic(itdms[2].getModifiers())); + assertEquals("one param, got: ",1,itdms[0].getParameterTypes().length); + assertEquals("expecting String, got: ",String.class,itdms[0].getParameterTypes()[0].getJavaClass()); + assertEquals("nothing thrown, but: ",0,itdms[1].getExceptionTypes().length); + assertEquals("expecting int, got: ",int.class,itdms[2].getReturnType().getJavaClass()); + itdms = itdTest.getITDMethods(); + assertEquals("expecting 1 method, got: ",1,itdms.length); + assertEquals("expecting method name a, got: ","a",itdms[0].getName()); + try { + InterTypeMethodDeclaration m = itdTest.getDeclaredITDMethod("b",AjTypeSystem.getAjType(A.class),AjTypeSystem.getAjType(String.class)); + assertEquals("expecting b, got: ","b",m.getName()); + } catch (NoSuchMethodException ex) { throw new RuntimeException("didn't find expected itdm"); } + try { + InterTypeMethodDeclaration m = itdTest.getITDMethod("d",AjTypeSystem.getAjType(A.class),AjTypeSystem.getAjType(String.class)); + throw new RuntimeException("Expected NoSuchMethodException not thrown"); + } catch (NoSuchMethodException ex) { } + } + + private static void checkITDFs(AjType itdTest) throws ClassNotFoundException { + InterTypeFieldDeclaration[] itdfs = itdTest.getDeclaredITDFields(); + assertEquals("expecting 3 declared fields, got: ",3, itdfs.length); + assertEquals("expecting field name f, got: ","f",itdfs[0].getName()); + assertEquals("expecting field name g, got: ","g",itdfs[1].getName()); + assertEquals("expecting field name h, got: ","h",itdfs[2].getName()); + assertEquals("expecting AjType",AjTypeSystem.getAjType(A.class),itdfs[0].getTargetType()); + assertEquals("expecting public field, got:",true,Modifier.isPublic(itdfs[0].getModifiers())); + assertEquals("expecting private field, got:",true,Modifier.isPrivate(itdfs[1].getModifiers())); + assertEquals("expecting non-public field, got:",false,Modifier.isPublic(itdfs[2].getModifiers())); + assertEquals("expecting int, got: ",int.class,itdfs[2].getType().getJavaClass()); + itdfs = itdTest.getITDFields(); + assertEquals("expecting 1 field, got: ",1, itdfs.length); + assertEquals("expecting field name f, got: ","f",itdfs[0].getName()); + try { + InterTypeFieldDeclaration f = itdTest.getDeclaredITDField("f",AjTypeSystem.getAjType(A.class)); + assertEquals("expecting f, got: ","f",f.getName()); + } catch(NoSuchFieldException ex) { throw new RuntimeException("didn't find expected itdf"); } + try { + InterTypeFieldDeclaration g = itdTest.getITDField("g",AjTypeSystem.getAjType(A.class)); + throw new RuntimeException("Expected NoSuchFieldException not thrown"); + } catch (NoSuchFieldException ex) { } + } + + private static void checkITDCs(AjType itdTest) throws ClassNotFoundException { + InterTypeConstructorDeclaration[] itdcs = itdTest.getDeclaredITDConstructors(); + assertEquals("expecting 3 declared constructors, got: ",3, itdcs.length); + InterTypeConstructorDeclaration pubDec = findPublicCons(itdcs); + InterTypeConstructorDeclaration privDec = findPrivateCons(itdcs); + InterTypeConstructorDeclaration defDec = findDefaultCons(itdcs); + if (pubDec == null || privDec == null || defDec == null) throw new RuntimeException("failed to find expected constructors"); + assertEquals("two params, got: ",2,defDec.getParameterTypes().length); + assertEquals("expecting String, got: ",String.class,defDec.getParameterTypes()[0].getJavaClass()); + assertEquals("expecting Object, got: ",Object.class,defDec.getParameterTypes()[1].getJavaClass()); + assertEquals("nothing thrown, but: ",0,privDec.getExceptionTypes().length); + itdcs = itdTest.getITDConstructors(); + assertEquals("expecting 1 cons, got: ",1,itdcs.length); + try { + InterTypeConstructorDeclaration c = itdTest.getDeclaredITDConstructor(AjTypeSystem.getAjType(A.class),AjTypeSystem.getAjType(String.class)); + } catch (NoSuchMethodException ex) { throw new RuntimeException("didn't find expected itdm"); } + try { + InterTypeConstructorDeclaration c = itdTest.getITDConstructor(AjTypeSystem.getAjType(A.class),AjTypeSystem.getAjType(String.class),AjTypeSystem.getAjType(Object.class)); + throw new RuntimeException("Expected NoSuchMethodException not thrown"); + } catch (NoSuchMethodException ex) { } + } + + private static InterTypeConstructorDeclaration findPublicCons(InterTypeConstructorDeclaration[] itcds) { + for( InterTypeConstructorDeclaration i : itcds) { + if (Modifier.isPublic(i.getModifiers())) { + return i; + } + } + return null; + } + + private static InterTypeConstructorDeclaration findPrivateCons(InterTypeConstructorDeclaration[] itcds) { + for( InterTypeConstructorDeclaration i : itcds) { + if (Modifier.isPrivate(i.getModifiers())) { + return i; + } + } + return null; + } + + private static InterTypeConstructorDeclaration findDefaultCons(InterTypeConstructorDeclaration[] itcds) { + for( InterTypeConstructorDeclaration i : itcds) { + if (!Modifier.isPublic(i.getModifiers()) && !Modifier.isPrivate(i.getModifiers())) { + return i; + } + } + return null; + } + + private static void checkAnnStyle() { + AjType x = AjTypeSystem.getAjType(X.class); + org.aspectj.lang.reflect.DeclareParents[] decps = x.getDeclareParents(); + assertEquals("1 declare parents",1,decps.length); + assertEquals("implements",true,decps[0].isImplements()); + assertEquals("X",x,decps[0].getDeclaringType()); + assertEquals("org.xyz..*, got: ","org.xyz..*",decps[0].getTargetTypesPattern().asString()); + try { + assertEquals("1: ",1,decps[0].getParentTypes().length); + assertEquals("I: ",I.class,((AjType)decps[0].getParentTypes()[0]).getJavaClass()); + } catch (ClassNotFoundException cnf) { + throw new RuntimeException(cnf); + } + assertEquals("1: ",1,x.getDeclaredITDFields().length); + assertEquals("i: ","i",x.getDeclaredITDFields()[0].getName()); + assertEquals("1: ",1,x.getITDMethods().length); + assertEquals("getNumber: ","getNumber",x.getITDMethods()[0].getName()); + } + + private static void assertEquals(String msg, Object expected, Object actual) { + if (!expected.equals(actual)) throw new RuntimeException(msg + " " + actual.toString()); + } +} + + +class A {} + +@Aspect +class X { + + @org.aspectj.lang.annotation.DeclareParents("org.xyz..*") + public static class Mixin implements I { + + private int i = 0; + + public int getNumber() { return i; } + + } + +} + +interface I { + + int getNumber(); + +} + diff --git a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml index ef3f9fcd4..3c0335717 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ajc150.xml @@ -4586,7 +4586,7 @@ - + @@ -4617,7 +4617,7 @@ - + @@ -4626,7 +4626,7 @@ - + @@ -4635,7 +4635,7 @@ - + @@ -4644,7 +4644,7 @@ - + @@ -4653,7 +4653,7 @@ - + @@ -4662,7 +4662,7 @@ - + @@ -4671,7 +4671,7 @@ - + @@ -4680,7 +4680,7 @@ - + @@ -4689,7 +4689,7 @@ - + @@ -4698,7 +4698,7 @@ - + @@ -4707,7 +4707,7 @@ - + @@ -4716,7 +4716,7 @@ - + @@ -4725,7 +4725,7 @@ - + @@ -4734,7 +4734,7 @@ - + @@ -4743,7 +4743,7 @@ - + @@ -4752,7 +4752,7 @@ - + @@ -4761,7 +4761,7 @@ - + @@ -4770,7 +4770,7 @@ - + @@ -4779,7 +4779,7 @@ - + @@ -4788,7 +4788,7 @@ - + @@ -4798,7 +4798,7 @@ - + @@ -4807,7 +4807,7 @@ - + @@ -4816,7 +4816,7 @@ - + @@ -4825,7 +4825,7 @@ - + @@ -4834,7 +4834,7 @@ - + @@ -4843,7 +4843,7 @@ - + diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java index c3711841f..27b562d62 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/AtAjAnnotationGenTests.java @@ -150,5 +150,9 @@ public class AtAjAnnotationGenTests extends XMLBasedAjcTestCase { public void testDecAnnotation() { runTest("ann gen for dec annotation"); } + + public void testITDs() { + runTest("ann gen for itds"); + } } diff --git a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml index 3e74a541a..33c28dbb3 100644 --- a/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml +++ b/tests/src/org/aspectj/systemtest/ajc150/ataspectj/annotationgen.xml @@ -177,5 +177,11 @@ - + + + + + + + \ No newline at end of file