| /******************************************************************************* |
| * Copyright (c) 2004 IBM Corporation and others. |
| * 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: |
| * Luzius Meisser - initial implementation |
| *******************************************************************************/ |
| package org.eclipse.ajdt.core.javaelements; |
| |
| import java.lang.reflect.Field; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.aspectj.asm.IHierarchy; |
| import org.aspectj.asm.IProgramElement; |
| import org.aspectj.asm.IProgramElement.Accessibility; |
| import org.aspectj.asm.IProgramElement.ExtraInformation; |
| import org.aspectj.asm.IProgramElement.Kind; |
| import org.aspectj.asm.internal.ProgramElement; |
| import org.aspectj.bridge.ISourceLocation; |
| import org.eclipse.ajdt.core.model.AJProjectModelFactory; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jdt.core.WorkingCopyOwner; |
| import org.eclipse.jdt.internal.core.JavaElement; |
| import org.eclipse.jdt.internal.core.SourceType; |
| import org.eclipse.jdt.internal.core.util.MementoTokenizer; |
| |
| /** |
| * @author Luzius Meisser |
| */ |
| public class AspectElement extends SourceType implements IAspectJElement { |
| |
| // characters to use for handle identifiers, alongside the ones in JavaElement |
| public static final char JEM_ASPECT_CU = '*'; |
| public static final char JEM_ADVICE = '&'; |
| public static final char JEM_ASPECT_TYPE = '}'; |
| public static final char JEM_CODEELEMENT = '?'; |
| public static final char JEM_ITD = ')'; |
| public static final char JEM_DECLARE = '`'; |
| public static final char JEM_POINTCUT = '+'; |
| // TYPE_PARAMETER is defined in Eclipse 3.1, but not 3.0 |
| public static final char JEM_TYPE_PARAMETER = ']'; |
| // public static final char JEM_EXTRA_INFO = '>'; |
| |
| public IMethod createMethod(String contents, IJavaElement sibling, |
| boolean force, IProgressMonitor monitor) throws JavaModelException { |
| IMethod result = super.createMethod(contents, sibling, force, monitor); |
| return result; |
| } |
| public AspectElement(JavaElement parent, String name) { |
| super(parent, name); |
| } |
| |
| public int getType() { |
| return TYPE; |
| } |
| |
| protected Object createElementInfo() { |
| AspectElementInfo info = new AspectElementInfo(); |
| info.setAJKind(IProgramElement.Kind.ASPECT); |
| info.setHandle(this); |
| info.setSourceRangeStart(0); |
| |
| IProgramElement ipe = AJProjectModelFactory.getInstance().getModelForJavaElement(this).javaElementToProgramElement(this); |
| if (ipe != IHierarchy.NO_STRUCTURE) { |
| info.setAJExtraInfo(ipe.getExtraInfo()); |
| info.setAJModifiers(ipe.getModifiers()); |
| info.setFlags(getProgramElementModifiers(ipe)); |
| info.setAJAccessibility(ipe.getAccessibility()); |
| ISourceLocation sourceLocation = ipe.getSourceLocation(); |
| info.setSourceRangeStart(sourceLocation.getOffset()); |
| info.setNameSourceStart(sourceLocation.getOffset()); |
| info.setNameSourceEnd(sourceLocation.getOffset() + ipe.getName().length()); |
| } |
| |
| |
| return info; |
| } |
| |
| /** |
| * Returns the pointcuts declared by this type. If this is a source type, |
| * the results are listed in the order in which they appear in the source, |
| * otherwise, the results are in no particular order. |
| * |
| * @exception JavaModelException |
| * if this element does not exist or if an exception occurs |
| * while accessing its corresponding resource. |
| * @return the pointcuts declared by this type |
| */ |
| public PointcutElement[] getPointcuts() throws JavaModelException { |
| // pointcuts appear as methods |
| IMethod[] methods = getMethods(); |
| List list = new ArrayList(); |
| for (int i = 0; i < methods.length; i++) { |
| if (methods[i] instanceof PointcutElement) { |
| list.add(methods[i]); |
| } |
| } |
| PointcutElement[] array= new PointcutElement[list.size()]; |
| list.toArray(array); |
| return array; |
| } |
| |
| /** |
| * Returns the advice elements declared by this type. If this is a source |
| * type, the results are listed in the order in which they appear in the |
| * source, otherwise, the results are in no particular order. |
| * |
| * @exception JavaModelException |
| * if this element does not exist or if an exception occurs |
| * while accessing its corresponding resource. |
| * @return the advice elements declared by this type |
| */ |
| public AdviceElement[] getAdvice() throws JavaModelException { |
| // advice statements appear as methods |
| IMethod[] methods = getMethods(); |
| List list = new ArrayList(); |
| for (int i = 0; i < methods.length; i++) { |
| if (methods[i] instanceof AdviceElement) { |
| list.add(methods[i]); |
| } |
| } |
| AdviceElement[] array = new AdviceElement[list.size()]; |
| list.toArray(array); |
| return array; |
| } |
| |
| /** |
| * Returns the declare elements declared by this type. If this is a source |
| * type, the results are listed in the order in which they appear in the |
| * source, otherwise, the results are in no particular order. |
| * |
| * @exception JavaModelException |
| * if this element does not exist or if an exception occurs |
| * while accessing its corresponding resource. |
| * @return the declare elements declared by this type |
| */ |
| public DeclareElement[] getDeclares() throws JavaModelException { |
| // declare statements appear as methods |
| IMethod[] methods = getMethods(); |
| List list = new ArrayList(); |
| for (int i = 0; i < methods.length; i++) { |
| if (methods[i] instanceof DeclareElement) { |
| list.add(methods[i]); |
| } |
| } |
| DeclareElement[] array = new DeclareElement[list.size()]; |
| list.toArray(array); |
| return array; |
| } |
| |
| /** |
| * Returns the declare elements declared by this type. If this is a source |
| * type, the results are listed in the order in which they appear in the |
| * source, otherwise, the results are in no particular order. |
| * |
| * @exception JavaModelException |
| * if this element does not exist or if an exception occurs |
| * while accessing its corresponding resource. |
| * @return the declare elements declared by this type |
| */ |
| public IntertypeElement[] getITDs() throws JavaModelException { |
| // ITDs statements appear as methods |
| IMethod[] methods = getMethods(); |
| List list = new ArrayList(); |
| for (int i = 0; i < methods.length; i++) { |
| if (methods[i] instanceof IntertypeElement) { |
| list.add(methods[i]); |
| } |
| } |
| IntertypeElement[] array = new IntertypeElement[list.size()]; |
| list.toArray(array); |
| return array; |
| } |
| |
| //TODO: forward call to ElementInfo (only for cosmetical reasons) |
| public Kind getAJKind() throws JavaModelException { |
| IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo(); |
| return info.getAJKind(); |
| } |
| |
| public Accessibility getAJAccessibility() throws JavaModelException { |
| IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo(); |
| return info.getAJAccessibility(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ajdt.javamodel.javaelements.IAspectJElement#getAJModifiers() |
| */ |
| public List getAJModifiers() throws JavaModelException { |
| IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo(); |
| return info.getAJModifiers(); |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.ajdt.javamodel.javaelements.IAspectJElement#getAJExtraInformation() |
| */ |
| public ExtraInformation getAJExtraInformation() throws JavaModelException { |
| IAspectJElementInfo info = (IAspectJElementInfo) getElementInfo(); |
| return info.getAJExtraInfo(); |
| } |
| |
| /** |
| * @see JavaElement#getHandleMemento() |
| */ |
| protected char getHandleMementoDelimiter() { |
| return AspectElement.JEM_ASPECT_TYPE; |
| } |
| |
| /* |
| * Derived from JEM_METHOD clause in SourceType |
| * Added support for advice, ITDs, and declare statements |
| * @see JavaElement |
| */ |
| public IJavaElement getHandleFromMemento(String token, MementoTokenizer memento, WorkingCopyOwner workingCopyOwner) { |
| if (token.charAt(0) == AspectElement.JEM_ADVICE) { |
| token = null; |
| if (!memento.hasMoreTokens()) return this; |
| String name = memento.nextToken(); |
| |
| ArrayList params = new ArrayList(); |
| nextParam: while (memento.hasMoreTokens()) { |
| token = memento.nextToken(); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| break nextParam; |
| case JEM_TYPE_PARAMETER: |
| token = null; |
| break nextParam; |
| case JEM_ADVICE: |
| if (!memento.hasMoreTokens()) return this; |
| String param = memento.nextToken(); |
| StringBuffer buffer = new StringBuffer(); |
| while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos |
| buffer.append(Signature.C_ARRAY); |
| if (!memento.hasMoreTokens()) return this; |
| param = memento.nextToken(); |
| } |
| params.add(buffer.toString() + param); |
| token = null; |
| break; |
| default: |
| break nextParam; |
| } |
| } |
| String[] parameters = new String[params.size()]; |
| params.toArray(parameters); |
| |
| JavaElement advice = new AdviceElement(this, name, parameters); |
| if (token != null) { |
| return advice.getHandleFromMemento(token, memento, workingCopyOwner); |
| } else { |
| return advice; |
| } |
| } else if (token.charAt(0) == AspectElement.JEM_ITD) { |
| String name = memento.nextToken(); |
| ArrayList params = new ArrayList(); |
| nextParam: while (memento.hasMoreTokens()) { |
| token = memento.nextToken(); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| case JEM_TYPE_PARAMETER: |
| break nextParam; |
| case JEM_ITD: |
| if (!memento.hasMoreTokens()) return this; |
| String param = memento.nextToken(); |
| StringBuffer buffer = new StringBuffer(); |
| while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos |
| buffer.append(Signature.C_ARRAY); |
| if (!memento.hasMoreTokens()) return this; |
| param = memento.nextToken(); |
| } |
| params.add(buffer.toString() + param); |
| break; |
| default: |
| break nextParam; |
| } |
| } |
| String[] parameters = new String[params.size()]; |
| params.toArray(parameters); |
| JavaElement itd = new IntertypeElement(this, name, parameters); |
| if (memento.hasMoreTokens()) { |
| return itd.getHandleFromMemento(token, memento, workingCopyOwner); |
| } else { |
| return itd; |
| } |
| } else if (token.charAt(0) == AspectElement.JEM_DECLARE) { |
| String name = memento.nextToken(); |
| ArrayList params = new ArrayList(); |
| nextParam: while (memento.hasMoreTokens()) { |
| token = memento.nextToken(); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| case JEM_TYPE_PARAMETER: |
| break nextParam; |
| case JEM_DECLARE: |
| if (!memento.hasMoreTokens()) return this; |
| String param = memento.nextToken(); |
| StringBuffer buffer = new StringBuffer(); |
| while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos |
| buffer.append(Signature.C_ARRAY); |
| if (!memento.hasMoreTokens()) return this; |
| param = memento.nextToken(); |
| } |
| params.add(buffer.toString() + param); |
| break; |
| default: |
| break nextParam; |
| } |
| } |
| String[] parameters = new String[params.size()]; |
| params.toArray(parameters); |
| JavaElement itd = new DeclareElement(this, name, parameters); |
| if (token.charAt(0) == JavaElement.JEM_COUNT) { |
| return itd.getHandleFromMemento(token, memento, workingCopyOwner); |
| } |
| return itd.getHandleFromMemento(memento, workingCopyOwner); |
| } else if (token.charAt(0) == AspectElement.JEM_POINTCUT) { |
| String name = memento.nextToken(); |
| ArrayList params = new ArrayList(); |
| nextParam: while (memento.hasMoreTokens()) { |
| token = memento.nextToken(); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| case JEM_TYPE_PARAMETER: |
| break nextParam; |
| case JEM_POINTCUT: |
| if (!memento.hasMoreTokens()) return this; |
| String param = memento.nextToken(); |
| StringBuffer buffer = new StringBuffer(); |
| while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos |
| buffer.append(Signature.C_ARRAY); |
| if (!memento.hasMoreTokens()) return this; |
| param = memento.nextToken(); |
| } |
| params.add(buffer.toString() + param); |
| break; |
| default: |
| break nextParam; |
| } |
| } |
| String[] parameters = new String[params.size()]; |
| params.toArray(parameters); |
| JavaElement pointcut = new PointcutElement(this, name, parameters); |
| return pointcut.getHandleFromMemento(memento, workingCopyOwner); |
| } else if (token.charAt(0) == AspectElement.JEM_METHOD && |
| ! (this.getOpenable() instanceof AJCompilationUnit)) { |
| // method must be mocked up if we are an aspect in a |
| // .class or .java file |
| // cannot get the JavaElementInfo otherwise |
| String name = memento.nextToken(); |
| ArrayList params = new ArrayList(); |
| nextParam: while (memento.hasMoreTokens()) { |
| token = memento.nextToken(); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| case JEM_TYPE_PARAMETER: |
| case JEM_ANNOTATION: |
| break nextParam; |
| case JEM_METHOD: |
| if (!memento.hasMoreTokens()) return this; |
| String param = memento.nextToken(); |
| StringBuffer buffer = new StringBuffer(); |
| while (param.length() == 1 && Signature.C_ARRAY == param.charAt(0)) { // backward compatible with 3.0 mementos |
| buffer.append(Signature.C_ARRAY); |
| if (!memento.hasMoreTokens()) return this; |
| param = memento.nextToken(); |
| } |
| params.add(buffer.toString() + param); |
| break; |
| default: |
| break nextParam; |
| } |
| } |
| String[] parameters = new String[params.size()]; |
| params.toArray(parameters); |
| MockSourceMethod mockMethod = new MockSourceMethod(this, name, parameters); |
| switch (token.charAt(0)) { |
| case JEM_TYPE: |
| case JEM_TYPE_PARAMETER: |
| case JEM_LOCALVARIABLE: |
| case JEM_ANNOTATION: |
| return mockMethod.getHandleFromMemento(token, memento, workingCopyOwner); |
| default: |
| return mockMethod; |
| } |
| } |
| return super.getHandleFromMemento(token, memento, workingCopyOwner); |
| } |
| |
| static Field modfiersField = null; |
| static int getProgramElementModifiers(IProgramElement ipe) { |
| try { |
| if (modfiersField == null) { |
| modfiersField = ProgramElement.class.getDeclaredField("modifiers"); |
| modfiersField.setAccessible(true); |
| } |
| return modfiersField.getInt(ipe); |
| } catch (SecurityException e) { |
| } catch (IllegalArgumentException e) { |
| } catch (NoSuchFieldException e) { |
| } catch (IllegalAccessException e) { |
| } |
| return -1; |
| } |
| |
| } |